2012-08-14 10 views
6

Sono nuovo di AutoFixture, quindi non so se la seguente idea avrà senso o essere una cosa ragionevole da fare. Ho un'applicazione che mi occupo del test di integrazione e fa un uso massiccio di Castle Windsor. Per semplificare la gestione delle dipendenze e rendere i miei test più simili al codice dell'applicazione, ho creato il contenitore Windsor nel mio metodo di inizializzazione del test e nell'utilizzo del contenitore. Risolvi per creare un'istanza del codice che sto testando. Mi piacerebbe allontanarmi da questo approccio poiché ha limitato la mia flessibilità in determinate situazioni.Tecnica per l'utilizzo di AutoFixture per l'integrazione di test di un'applicazione utilizzando Castle Windsor

Quello che mi piacerebbe fare è di avere le prove che sembrano qualcosa di simile:

[Theory] 
[Dependency] 
public void TestWithDependencies(IThing thing) 
{ 
    thing.Hello(); 
} 

per rendere questo accada, posso effettuare le seguenti operazioni:

public sealed class DependencyAttribute : AutoDataAttribute 
{ 
    public DependencyAttribute() 
     : base(new Fixture().Customize(new WindsorCustomization())) 
    { 
    } 
} 

public class WindsorCustomization : ICustomization 
{ 
    public WindsorCustomization() 
    { 
     // build container here using SUT installers 
    } 

    public void Customize(IFixture fixture) 
    { 
     fixture.Inject<IThing>(new Thing()); 
    } 
} 

Facendo questo funziona, ma quello che vorrei evitare è la necessità di copiare ogni interfaccia per la mappatura dell'implementazione dal container Windsor in AutoFixture IFixture.

+0

Welp! Ho appena dato un'occhiata al codice di AutoMoq e ho visto esattamente come fare ciò che voglio fare. Posso postare il codice in una risposta se qualcuno è interessato. – thebeekeeper

+0

Sì, è molto simile a come funziona AutoMoq :) –

risposta

6

Si dovrebbe essere in grado di fare qualcosa di simile:

public class WindsorCustomization : ICustomization 
{ 
    private readonly IWindsorContainer container; 

    public WindsorCustomization() 
    { 
     // build this.container here using SUT installers 
    } 

    public void Customize(IFixture fixture) 
    { 
     fixture.Customizations.Add(new WindsorAdapter(this.container)); 
    } 
} 

public WindsorAdapter : ISpecimenBuilder 
{ 
    private readonly IWindsorContainer container; 

    public WindsorAdapter(IWindsorContainer container) 
    { 
     this.container = container; 
    } 

    public object Create(object request, ISpecimenContext context) 
    { 
     var t = request as Type; 
     if (t == null || !this.container.Kernel.HasComponent(t)) 
      return new NoSpecimen(request); 

     return this.container.Resolve(t);     
    } 
} 

Il WindsorAdapter siede nella collezione Customizations, che è abbastanza presto in Albero della responsabilità di AutoFixture, quindi ha la possibilità di gestire ogni (o quasi) richieste in arrivo. Se la richiesta è un'istanza di tipo e WindsorContainer ha un componente per quel tipo, l'adattatore delega il lavoro di risoluzione del tipo al contenitore.

In caso contrario, restituisce un'istanza NoSpecimen, che è fondamentalmente la modalità di segnalazione di AutoFixture che questo particolare ISpecimenBuilder non è in grado di gestire la richiesta. Alcuni altri componenti nell'albero di responsabilità di AutoFixture hanno quindi la possibilità di gestire la richiesta.

+1

Sì, è esattamente quello che ho fatto. La parte interessante di questo è che siccome sto testando il codice che è solo 1/3 implementato, dovrei essere in grado di usare AutoMoq per sostituire il codice che non esiste e testare ancora il codice che esiste. Grande biblioteca! – thebeekeeper

+0

Sì, devi solo assicurarti che AutoMoqCustomization arrivi prima/dopo: http://blog.ploeh.dk/2012/07/31/TheOrderOfAutoFixtureCustomizationsMatter.aspx –