2012-02-12 17 views
21

Ja próbuje użyć zamku Windsor w moich zautomatyzowanych testów tak:w zamku Windsor 3, zastąpić istniejący rejestracji komponentu w badanej jednostki

Na każdym teście:

  • Funkcja Setup() tworzy pojemnik Windsor, rejestracji domyślne implementacje każdego składnika
  • The Test funkcji dostępu komponentów metodą IWindsorContainer.Resolve<T>, a testy ich zachowanie
  • TearDown() unieszkodliwia funkcyjne pojemnika Windsor (i wszelkie utworzone składniki)

Na przykład, mogę mieć 15 testów, które uzyskuje dostęp elementów pośrednio prowadzi do utworzenia z komponentu IMediaPlayerProxyFactory. Funkcja SetUp rejestruje wystarczająco dobrą implementację IMediaPlayerProxyFactory, więc nie mam ciężaru konserwacyjnego związanego z rejestracją tego w każdym z 15 testów.

Jednak teraz piszę test Test_MediaPlayerProxyFactoryThrowsException, potwierdzając, że mój system elegancko obsługuje błąd z komponentu IMediaPlayerProxyFactory. W metodzie badania stworzyłem moją szczególną realizację makiety, a teraz chcę, aby wprowadzić go w ramy:

this.WindsorContainer.Register(
           Component.For<IMediaPlayerProxyFactory>() 
              .Instance(mockMediaPlayerProxyFactory) 
          ); 

Ale Windsor rzuca Castle.MicroKernel.ComponentRegistrationException z komunikatem „Jest już komponent o tej nazwie. "

Czy jest jakiś sposób, aby ustawić mockMediaPlayerProxyFactory jako domyślną instancję dla IMediaPlayerProxyFactory, odrzucając komponent, który jest już zarejestrowany?


Według documentation, Windsor Castle 3 pozwala na zadajnikami rejestracyjnych, ale udało mi się znaleźć tylko jeden przykład:

Container.Register(
    Classes.FromThisAssembly() 
     .BasedOn<IEmptyService>() 
     .WithService.Base() 
     .ConfigureFor<EmptyServiceA>(c => c.IsDefault())); 

ConfigureFor jest metodą klasy BasedOnDescriptor. W moim przypadku nie używam FromDescriptor ani BasedOnDescriptor.

Odpowiedz

55

Są dwie rzeczy, które trzeba zrobić, aby utworzyć nadrzędną instancję:

  1. przypisać mu unikalną nazwę
  2. wywołać metodę IsDefault

Więc aby uzyskać przykład zadziałał :

this.WindsorContainer.Register(
          Component.For<IMediaPlayerProxyFactory>() 
             .Instance(mockMediaPlayerProxyFactory) 
             .IsDefault() 
             .Named("OverridingFactory") 
         ); 

Ponieważ planuję użyć tego opatrzonego patentów w wielu testach, jakie stworzył własną metodę rozszerzenia:

public static class TestWindsorExtensions 
{ 
    public static ComponentRegistration<T> OverridesExistingRegistration<T>(this ComponentRegistration<T> componentRegistration) where T : class 
    { 
     return componentRegistration 
          .Named(Guid.NewGuid().ToString()) 
          .IsDefault(); 
    } 
} 

Teraz przykład można uprościć do:

this.WindsorContainer.Register(
          Component.For<IMediaPlayerProxyFactory>() 
             .Instance(mockMediaPlayerProxyFactory) 
             .OverridesExistingRegistration() 
         ); 


później Edycja

Wersja 3.1 wprowadza IsFallback metoda. Jeśli zarejestruję wszystkie moje początkowe komponenty za pomocą IsFallback, wszelkie nowe rejestracje automatycznie zastąpią te początkowe rejestracje. Poszedłbym tą ścieżką, gdyby funkcjonalność była dostępna w tym czasie.

https://github.com/castleproject/Windsor/blob/master/docs/whats-new-3.1.md#fallback-components

+0

Nazywanie i wywoływanie metody '.IsDefault' nie są wymagane w rzeczywistej implementacji, poza tym, bardzo ładne! – bevacqua

+1

Dziękujemy za zaktualizowanie odpowiedzi. –

1

Nie należy ponownie używać pojemnika podczas testów. Zamiast tego ustaw go na null w TearDown() i ponownie zainicjuj go dla każdego rzeczywistego testu.

+0

Przepraszam, nie mogłem być jasne. Pozbywam się kontenera w 'TearDown()' i ponownie go inicjalizuję w 'SetUp()'. Zmienię moje intro, by spróbować to bardziej wyrazić. –