2012-08-14 17 views
6

Jestem nowy w AutoFixture, więc nie wiem, czy poniższy pomysł będzie sensowny, czy rozsądny. Mam aplikację, która jest odpowiedzialna za test integracji , i to sprawia, że ​​intensywne korzystanie z Castle Windsor. Aby uprościć zarządzanie zależnościami i sprawić, by moje testy bardziej przypominały kod aplikacji, budowałem kontener Windsor w mojej metodzie inicjowania testu i korzystałem z container.Resolve do tworzenia kodu, który testuję. Chciałbym odejść od tego podejścia, ponieważ ograniczyło to moją elastyczność w pewnych sytuacjach.Technika korzystania z AutoFixture do testowania integracji aplikacji korzystającej z Castle Windsor

Co chciałbym zrobić, to mieć testy, które wyglądają mniej więcej tak:

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

aby tak się stało, mogę wykonać następujące czynności:

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()); 
    } 
} 

Rozwiązanie to działa, ale to, czego chciałbym uniknąć, to kopiowanie każdego interfejsu do mapowania implementacji z kontenera Windsor na moduł IFIXture AutoFixture.

+0

Welp! Po prostu rzuciłem okiem na kod dla AutoMoq i zobaczyłem dokładnie, jak robić to, co chcę robić. Mogę opublikować kod w odpowiedzi, jeśli ktoś jest zainteresowany. – thebeekeeper

+0

Tak, to całkiem blisko do działania AutoMoqa :) –

Odpowiedz

6

Powinieneś być w stanie zrobić coś takiego:

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);     
    } 
} 

WindsorAdapter siedzi w kolekcji Customizations, co jest dość wcześnie w drzewo AutoFixture za odpowiedzialności, więc dostaje szansę, aby obsłużyć każdy (lub najbardziej) przychodzące żądania. Jeśli żądanie jest instancją typu, a WindsorContainer ma komponent dla tego typu, adapter deleguje pracę polegającą na rozdzieleniu tego typu na kontener.

W przeciwnym razie zwraca instancję NoSpecimen, która jest w zasadzie sposobem AutoFixture sygnalizowania, że ​​ten konkretny ISpecimenBuilder nie może obsłużyć żądania. Jakiś inny składnik w Drzewie Odpowiedzialności AutoFixture ma szansę obsłużyć żądanie.

+1

Tak, dokładnie to zrobiłem. Ekscytującą częścią tego jest to, że skoro testuję kod, który jest zaimplementowany tylko w 1/3, powinienem móc użyć AutoMoq, aby stanąć za nieistniejącym kodem i przetestować istniejący kod. Świetna biblioteka! – thebeekeeper

+0

Tak, wystarczy upewnić się, że AutoMoqCustomization pojawi się na końcu/później: http://blog.ploeh.dk/2012/07/31/TheOrderOfAutoFixtureCustomizationsMatter.aspx –

Powiązane problemy