2015-01-07 86 views
16

È possibile assegnare un valore fisso a una proprietà su un'istanza figlio durante la creazione di un genitore con Autofixture? Aggiungerà valori predefiniti a tutte le proprietà dell'istanza figlio come un incantesimo, ma vorrei sovrascrivere e assegnare un valore specifico a una delle proprietà sull'istanza figlio.Impostazione del valore della proprietà sull'istanza figlio su un valore fisso con Autofixture

Dato questo rapporto/genitore-figlio:

public class Person 
{ 
    public string FirstName { get; set; } 
    public string LastName { get; set; } 

    public Address Address { get; set; } 
} 

public class Address 
{ 
    public string Street { get; set; } 
    public int Number { get; set; } 
    public string City { get; set; } 
    public string PostalCode { get; set; } 
} 

vorrei assegnare un valore specifico alla proprietà Città sull'istanza indirizzo. Stavo pensando alle righe di questo codice di test:

var fixture = new Fixture(); 

var expectedCity = "foo"; 

var person = fixture 
    .Build<Person>() 
    .With(x => x.Address.City, expectedCity) 
    .Create(); 

Assert.AreEqual(expectedCity, person.Address.City); 

Questo non è possibile. Credo che, per l'eccezione riflessione

System.Reflection.TargetException : Object does not match target type. 

... che Autofixture cerca di assegnare il valore ad una proprietà della città nell'istanza persona invece di un'istanza Indirizzo.

Qualche suggerimento?

E sì, lo so che ho potuto solo aggiungere un ulteriore passaggio simile al seguente:

var fixture = new Fixture(); 

var expectedCity = "foo"; 

// extra step begin 
var address = fixture 
    .Build<Address>() 
    .With(x => x.City, expectedCity) 
    .Create(); 
// extra step end 

var person = fixture 
    .Build<Person>() 
    .With(x => x.Address, address) 
    .Create(); 

Assert.AreEqual(expectedCity, person.Address.City); 

... ma speravo per la prima versione o qualcosa di simile (meno passaggi, più terse).

Nota: sto usando Autofixture v3.22.0

+0

correlati: http://stackoverflow.com/a/11657881/11635 –

risposta

5

Non ignorare la domanda, ma la soluzione più semplice potrebbe essere:

[Fact] 
public void SimplestThingThatCouldPossiblyWork() 
{ 
    var fixture = new Fixture(); 
    var expectedCity = "foo"; 
    var person = fixture.Create<Person>(); 
    person.Address.City = expectedCity; 
    Assert.Equal(expectedCity, person.Address.City); 
} 

L'assegnazione di valori espliciti alle proprietà è qualcosa che la maggior parte delle lingue già eccellono (C# certamente lo è), quindi non credo che AutoFixture abbia bisogno di un DSL complicato per riprodurre metà della funzionalità.

+0

Mentre è ovvio per la maggior parte di noi che l'assegnazione di valori espliciti alle proprietà in C# è (quasi) senza sforzo, il La domanda originale era che io in una relazione genitore/figlio assegnassi un valore fisso a una proprietà del bambino _con_Funtura autofirmata. La ragione della domanda è semplicemente sull'estetica, poiché penso che raggruppare le assegnazioni di valori usando la sintassi .With (...) sarebbe "più carina" quando si hanno incarichi multipli (così soggettivamente). A parte l'estetica, la tua risposta ha portato a termine il lavoro. –

+0

È possibile correggere un valore implementando un 'ISpecimenBuilder' personalizzato, ma non (penso) con il DSL fluente, quando si tratta di una proprietà Train Wreck. Ho avuto l'impressione dalla domanda che stavi mirando alla bellezza, ma se vuoi un approccio basato sulla convenzione, sarò felice di condividerlo. –

+0

No, ma grazie lo stesso. Il relitto del treno è parcheggiato al limite estremo della mia applicazione e modella semplicemente una struttura di dati in entrata, quindi vivrò con una manciata di casi di test che sembrano ... beh ... meno belli ;-) –

-1

È possibile utilizzare un fare metodo sul costruttore:

var person = this.fixture 
       .Build<Person>() 
       .Do(x => x.Address.City = expectedCity) 
       .Create(); 

È inoltre possibile iniettare e congelare l'istanza per l'apparecchio:

this.fixture.Inject(expectedCity); 
+0

avete effettivamente provato a r un codice? Getta una NullReferenceException quando la eseguo. –

+0

...e Inject imposterà tutte le proprietà della stringa sul valore di expectedCity - non proprio quello che voglio –

+0

Infatti, esiste una NullReferenceException per il metodo * Do *, quale IMO può essere considerato un bug, perché questo metodo proviene dall'interfaccia denominata * IPostprocessComposer *, quindi la post-elaborazione deve essere eseguita dopo che l'oggetto e le sue dipendenze sono state create. – sgnsajgon

9

Per completezza, ecco un altro modo per farlo:

fixture.Customize<Address>(c => 
    c.With(addr => addr.City, "foo")); 

var person = fixture.Create<Person>(); 

Ciò personalizzare la creazione di tutte le istanze di Address

Se si finisce per utilizzare questo abbastanza spesso, può essere utile avvolgendolo all'interno di un ICustomization:

public class AddressConventions : ICustomization 
{ 
    public void Customize(IFixture fixture) 
    { 
     fixture.Customize<Address>(c => 
      c.With(addr => addr.City, "foo")); 
    } 
} 

fixture.Customize(new AddressConventions());