2012-09-03 43 views
1

我有被打開兩個WCF服務的Windows服務。我想單元測試OnStart()並聲明service1.Open()和service2.Open()被調用。的OnStart()看起來是這樣的:如何確認打開()被調用我的ServiceHost在我的單元測試

protected override void OnStart(string[] args) 
{ 
    // host WCF services    
    _service1.Open();   
    _service2.Open(); 
} 

我注射服務的構造函數重載這樣:

public WinService(ServiceHostBase service1, 
            ServiceHostBase service2) 
{ 
    _service1 = service1; 
    _service2 = service2; 
    InitializeComponent(); 
} 

我使用RhinoMocks產生ServiceHostBase的存根這樣的:

[TestMethod()] 
public void WinServiceOnStartCallsDependenciesAsExpected() 
{ 
    ServiceHostBase service1 = MockRepository.GenerateStub<ServiceHostBase>(); 
    ServiceHostBase service2 = MockRepository.GenerateStub<ServiceHostBase>(); 
    WinService target = new WinService(service1, service2); 
    WinService_Accessor privateTarget = new WinService_Accessor(new PrivateObject(target));  
    privateTarget.OnStart(null); 

當我的測試呼叫的OnStart(),我得到一個空引用異常時,它調用service1.Open()。我已經確認service1是一個模擬對象,並且它是Open(),它拋出了null。我知道Open()實際上是System.ServiceModel.Channels.CommunicationObject上的一個方法,我嘗試了Stubbing或Mocking,但我仍然得到對象ref錯誤。這不是一個虛擬的方法,所以我認爲它只是不被嘲笑的版本覆蓋,但是當我試圖建立一個預期reportservice.Stub(r => r.Open()),我得到一個不同的異常大約有不是一個默認的超時時間,因爲如果它運行的實際CommunicationObject Open()方法,而不是引發null參考的RhinoMocky。

這一切說,我只是尋求幫助,如何確認打開()被調用我在單元測試的ServiceHost。 =]

回答

1

ServiceHostBase.Open呼叫引擎蓋下CommunicationObject.Open。作爲其實施的一部分,它執行許多不同的事情 - 例如驗證對象的狀態,創建其他對象,調用方法,屬性等等。由於它不是虛擬的(你的假設是正確的),Rhino將調用基類實現。

要使其工作,你可能不得不嘲笑和存根很多CommunicationObject依賴性,它仍然不會是某些是否會成功與否(某些類型/方法可能只是unmockable犀牛,認爲靜態,密封或其他非虛擬)。這就是爲什麼你應該:

  1. 將這種測試留給集成測試;您將在最終用戶環境中測試.Open
  2. ServiceHostBase附近引入wrapper並將其作爲依賴接口傳遞;這需要額外的工作(新的界面和簡單的包裝類),但可以讓你做你想要什麼

請記住,增加包裝只會進一步下放的問題(以包裝類Open方法,基本上將調用ServiceHostBase.Open - 你應該單元測試嗎?)。另一方面,集成測試可能不像單元測試那樣快(如果不經常運行它們),則會遇到問題。根據您認爲OnOpen的重要程度如何,您選擇哪種方式或多或少是一種判斷。

+0

是啊,我是辯論的包裝方法,但我認爲,我們只是將不得不離開它發現。 Open()調用永遠不會是有條件的,所以風險似乎不會讓額外的複雜性值得。如果沒有驚人的驚喜出現,我會將其標記爲答案。 – sonicblis

相關問題