2012-02-12 60 views
21

我試圖使用城堡溫莎在我的自動化測試像這樣:在城堡溫莎3,覆蓋現有的組件註冊在一個單元測試

在每一個試驗:

  • Setup()函數創建一個溫莎容器,登記每個組件的默認的實現
  • Test功能訪問通過該方法IWindsorContainer.Resolve<T>組分,並測試它們的行爲
  • TearDown()函數處理溫莎容器(以及任何創建的組件)

例如,我可能有15個測試訪問組件,間接導致創建IMediaPlayerProxyFactory組件。 SetUp函數註冊了一個足夠好的實現IMediaPlayerProxyFactory,所以我沒有在15個測試的每一箇中註冊這個維護的負擔。

不過,我現在寫一個測試Test_MediaPlayerProxyFactoryThrowsException,優雅確認我的系統處理來自IMediaPlayerProxyFactory組件的錯誤。在測試方法我已經建立了我特殊的模擬實現,現在我想將它注入框架:

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

但溫莎拋出一個Castle.MicroKernel.ComponentRegistrationException,與消息「已經有該名稱的組成部分。 「

有沒有什麼辦法可以讓我的mockMediaPlayerProxyFactory成爲IMediaPlayerProxyFactory的默認實例,丟棄已經註冊的組件?


按照 documentation,城堡溫莎3允許登記覆蓋,但我只找到一個例子:

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

ConfigureForBasedOnDescriptor類的方法。在我的情況下,我沒有使用FromDescriptorBasedOnDescriptor

回答

55

有兩件事情是你必須做的創建一個覆蓋實例:

  1. 給它分配一個唯一的名稱
  2. 調用IsDefault方法

因此,要獲得該示例工作:

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

因爲我打算使用這個壓倒一切的模式在很多測試中,我創建了自己的擴展方法:

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

現在的例子可以簡化爲:

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


後來編輯

3.1版引入了IsFallback方法。如果我用IsFallback註冊我的所有初始組件,則任何新的註冊將自動覆蓋這些初始註冊。如果功能在當時可用,我會走下這條路。

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

+0

命名和調用'.IsDefault'方法不需要真正的實現,除此之外,非常好! – bevacqua 2012-05-02 03:33:33

+1

感謝您更新答案。 – 2013-12-16 09:23:08

1

請勿在測試中重複使用您的容器。相反,在TearDown()中將其設置爲null,併爲每次實際測試重新初始化它。

+0

對不起,我不能一直不清楚。我在'TearDown()'中處理容器,然後在'SetUp()'中重新初始化它。我會改變我的介紹,嘗試更加明確。 – 2012-02-12 23:06:00