Autofixture: Beschuldigt Readonly für eine Eigenschaft, die nicht ReadOnly ist

Erstellt am 4. Juni 2013  ·  4Kommentare  ·  Quelle: AutoFixture/AutoFixture

In meiner Domänenebene haben Sie die Klasse:

public class Telefone : IEntity
{
    public virtual int Id { get; protected internal set; }
    public virtual string Tipo { get; set; }
    public virtual string Numero { get; set; }
}

Die ID ist intern geschützt. Dies ist beabsichtigt, wer die Id generiert, ist die Datenbank und sollte ReadOnly sein.
Aber in der Testschicht muss Zugriff auf den Setter dieser Eigenschaft bestehen.

In meiner Domänenebene wurde das Attribut in AssemblyInfo.cs hinzugefügt:

[assembly: InternalsVisibleTo("MyTestLayer")]

Dadurch kann ich die ID in der Testebene festlegen, jedoch nicht in der Domänenebene!

In Testschicht
neues Telefon().Id = 1; // Funktioniert!!

In der UI-Ebene
neues Telefon().Id = 1; // Nicht kompilieren! Funktioniert nicht!

Problem

var pessoa = fix.Build<Pessoa>()
    .With(p => p.Nome)
    .Do((pess) =>
    {
        fix.Build<Telefone>()
            .With(p => p.Id)
            .With(p => p.Tipo)
            .With(p => p.Numero)
            .OmitAutoProperties()
            .CreateMany(10).ToList().ForEach(pess.Telefones.Add);

        fix.Build<Email>()
            .With(p => p.Id)
            .With(p => p.Tipo)
            .With(p => p.Endereco)
            .OmitAutoProperties()
            .CreateMany(10).ToList().ForEach(pess.Emails.Add);
    })
    .OmitAutoProperties()
    .Create();

Theoretisch sollte der obige Code funktionieren, aber bei meinem Fahrtest tritt ein Fehler auf:

Die Eigenschaft "Id" ist schreibgeschützt.

Alle Eigenschaften Id s sind protected internal .

In derselben Datei kann derselbe Test Folgendes tun:

neues Telefon().Id = 1; // Funktioniert!!
neue E-Mail().Id = 1; // Funktioniert!!

question

Alle 4 Kommentare

Dies sagt Ihnen eindeutig, dass Sie eine _undichte Abstraktion_ in Ihrem Domänenmodell haben. Ein Domänenmodell sollte nicht unter Berücksichtigung einer bestimmten Grenztechnologie entworfen werden.

Dieses spezielle Problem sagt Ihnen ganz klar, dass Ihr Domänenmodell _nicht_ wiederverwendbar ist.

InternalsVisibleTo hat keine Auswirkung, da es nur den Zugriff auf Ihre Testbibliothek ermöglicht, aber AutoFixture ist eine völlig andere Baugruppe. Dies sagt Ihnen nur, dass _kein_ andere Client jemals in der Lage sein wird, Ihr Domänenmodell wiederzuverwenden.

Am besten überdenken Sie Ihr API-Design. Normalerweise würde ich sowas machen:

``` c#
Telefon der öffentlichen Klasse: IEntity
{
öffentliches Telefon (int id)
{
this.Id = id;
}

public virtual int Id { get; private set; }
public virtual string Tipo { get; set; }
public virtual string Numero { get; set; }

}
```

Dies führte zu vielen Diskussionen in einer Gruppe von Architekturen, denen ich folge.
Bei diesem Ansatz gibt es ein großes Problem:

  1. Verantwortlich für die Generierung der Id ist die Datenbank, sie wird erst beim Speichern des Objekts generiert.
  2. Wenn ich ein neues Objekt erstelle, welche Id muss im Konstruktor übergeben werden? Ich kann die ID nicht in den Konstruktor einfügen.
  3. Die ID ist eine int-Sequenz. Die Repository-Schicht ist die nächste Schicht der Domäne. Um die ID zu generieren, würde man etwas wie max (id) + 1 tun und dann die ID meines Objekts festlegen. Aber wie stellt man die ID ein, wenn sie schreibgeschützt ist?
  4. Die einzige Möglichkeit, die ID von in einer ReadOnly-Eigenschaft festzulegen, ist innerhalb der Klasse selbst oder mithilfe eines Proxys/einer Reflexion

Einverstanden, dass dies alles _Probleme_ sind. Alle vier weisen _stark_ darauf hin, dass das Domänenmodell von der Persistenzschicht abhängt und ohne sie nicht zum Laufen gebracht werden kann.

  1. Warum sollte die Datenbank IDs zuweisen? Einzige Voraussetzung ist, dass eine ID eindeutig ist. Aus diesem Grund haben wir GUIDs.
  2. Übergeben Sie eine neue Guid-Instanz an den Konstruktor.
  3. Warum ist die ID sequentiell? Es gibt selten einen architektonischen Grund dafür, dass IDs sequenziell sind.
  4. Einverstanden. Es gibt einen Grund, warum Zugriffsmodifikatoren existieren.

Ich verstehe das Problem. Ich kann den PKs-Typ nicht in Guid ändern, würde wirklich funktionieren.

Ich verstehe jetzt, dass das Problem nicht mit AutoFixture zusammenhängt, aber wenn Sie interessiert sind. Ich erstelle ein Beispielprojekt , um dies zu diskutieren.

Danke.

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen