2016-07-31 8 views
4

Ich versuche Autoftixtur zu verwenden, um ein Objekt zu erstellen, aber sie sind bestimmte Eigenschaften, die ich immer voreinstellen möchte (während der Rest automatisch generiert werden konnte). Wann immer ich eine Anpassung einstelle, wird sie jedoch beim Erstellen mit Anpassungen überschrieben.Wie wird AutoFixture verwendet, um mit benutzerdefinierten Eigenschaften zu erstellen, während Typanpassungen beibehalten werden?

void Main() 
{ 
    var fixture = new Fixture(); 
    fixture.Customize<Person>(composer => composer.With(p => p.Name, "Ben")); 

    var person = fixture.Build<Person>() 
     .With(p => p.DateOfBirth, new DateTime(1900, 1, 1)) 
     .Create(); 

    /* RESULT OF person below 
    Name null 
    DateOfBirth 1/1/1900 
    StreetAddress StreetAddressafd6b86b-376a-4355-9a9c-fbae34731453 
    State State019e867b-ac5e-418f-805b-a64146bc06bc 
    */ 
} 

public class Person 
{ 
    public string Name { get; set;} 

    public DateTime DateOfBirth { get; set;} 

    public string StreetAddress { get; set;} 

    public string State { get; set;} 
} 

Der „Name“ und „DateOfBirth“ Eigenschaft Anpassung nicht in Konflikt, so weiß ich nicht, warum null seinen Name endet. Ich würde erwarten, dass der Name "Ben" ist. .?

Wie kann ich es bekommen, so dass beide Anpassungen angewendet werden (dh Name = "Ben" und DateOfBirth = 1.1.1900

Antwort

6

Wie @DavidOsborne richtig darauf hingewiesen, ist das Verhalten, das Sie sehen, as designed.

Ein better approach dient dazu, Ihre Anpassungen in separaten Klassen zu organisieren und dann nach Bedarf für ein bestimmtes Testszenario zu aktivieren.

Ein Anpassungsobjekt implementiert die Schnittstelle ICustomization, und sein Auftrag besteht darin, das Objekt Fixture auf eine bestimmte Weise zu konfigurieren. Hier ein Beispiel:

public class AllPersonsAreNamedBen : ICustomization 
{ 
    public void Customize(IFixture fixture) 
    { 
     fixture.Customize<Person>(composer => 
      composer.With(p => p.Name, "Ben")); 
    } 
} 

public class AllPersonsAreBornIn1900 : ICustomization 
{ 
    public void Customize(IFixture fixture) 
    { 
     fixture.Customize<Person>(composer => 
      composer.With(p => p.DateOfBirth, new DateTime(1900, 1, 1))); 
    } 
} 

Sie eine Anpassung auf einem bestimmten Fixture unter Verwendung des Customize Verfahren, beispielsweise ermöglichen kann:

fixture.Customize(new AllPersonsAreNamedBen()); 

oder:

fixture.Customize(new AllPersonsAreBornIn1900()); 

Sie können auch kombinieren mehrere Anpassungen in eine neue mit der CompositeCustomization Klasse:

public class AllPersonsAreNamedBenAndAreBornIn1900 : CompositeCustomization 
{ 
    public AllPersonsAreNamedBenAndAreBornIn1900() 
     : base(new AllPersonsAreNamedBen(), 
       new AllPersonsAreBornIn1900()) 
    { 
    } 
} 

an welcher Stelle Sie einfach sagen kann:

fixture.Customize(new AllPersonsAreNamedBenAndAreBornIn1900()); 

jedoch bedenken, dass die Reihenfolge, in der die Anpassungen auf einem Fixture Angelegenheiten angewendet werden: die letzten Siege und kann potenziell Überschreibung die vorherige, wie @MarkSeemann in den Kommentaren darauf hingewiesen hat. Dies ist auch by design.

So, während Sie können kombinieren Anpassungen bestehender, die auf verschiedenen Typen arbeiten, in diesem speziellen Fall, da beide Anpassungen des gleichen Typs Ziel, werden Sie eine neue Anpassungs erstellen müssen, um alle Einstellungen zu kapseln für die Person Art kombiniert:

public class AllPersonsAreNamedBenAndAreBornIn1900 : CompositeCustomization 
{ 
    public void Customize(IFixture fixture) 
    { 
     fixture.Customize<Person>(composer => 
      composer.With(p => p.Name, "Ben") 
        .With(p => p.DateOfBirth, new DateTime(1900, 1, 1))); 
    } 
} 

Als allgemeine Regel gilt, Ihre Anpassungen klein und halten fokussierte Sie in verschiedenen Tests zu reuse them ermöglicht, sich für bestimmte Testszenarien kombinieren.

+1

Wird 'AllPersonsAreNamedBen' nicht zu [override] (http://blog.ploeh.dk/2012/07/31/TheorderofAutoFixtureCustomizationsmatter)' AllPersonsAreBornIn1900'? –

+0

Ich stehe korrigiert. Da beide Anpassungen auf denselben Typ angewendet werden, werden sie absolut. Danke, dass du es angerufen hast! Dies ist ein Aspekt von AutoFixture, der mich von Zeit zu Zeit beißt - ich wünschte, ich könnte mehrere Anpassungen inkrementell so kombinieren, dass ich * * * * manchmal vergesse, dass es nicht möglich ist. –

+0

Ich habe meine Antwort aktualisiert, um den Fehler zu korrigieren. –

6

Das sieht aus wie es durch Design ist:

Beachten Sie, dass Die Build-Methodenkette wird am besten als einmalige Anpassung verstanden und umgeht alle Anpassungen auf der Instanz Fixture. Stattdessen ermöglicht sie eine feinkörnige Kontrolle beim Erstellen einer bestimmten Probe, wobei jedoch in den meisten Fällen ein konventionsbasiertes ICustomization hinzugefügt wird eine bessere, flexiblere Option

... aus der Dokumentation der Methode Build().

Ich schätze, dass dies wahrscheinlich keine ideale Antwort ist. Die Dokumentation gibt jedoch einen Hinweis darauf, wie Sie zu einem gelangen können.

Verwandte Themen