2010-05-21 54 views
2

假設我想編寫一個單元測試來測試方法中實現的特定功能。如果我想完全執行這個方法,我將不得不做一些額外的安裝工作(模擬對象期望等)。而不是這樣做,我使用以下方法:
- 我設置了我有興趣驗證的期望值,然後使測試方法拋出特殊類型的異常(例如TerminateTestException)。
- 進一步在單元測試中,我發現異常並驗證模擬對象的期望值。投擲特殊類型的異常終止單元測試

它工作正常,但我不確定這是不錯的做法。我不會定期這樣做,只有在節省時間和精力的情況下。有一點可以想到,使用它的一個理由是拋出異常需要很長時間,所以測試的執行速度比使用不同方法時要慢。編輯:
只是爲了澄清,我不修改SUT代碼。我所做的是提供一個模擬對象或重寫SUT類,以便在我感興趣的部分執行後SUT退出執行。

private class TestCalculationService : CalculationService 
    { 
     public bool ValidateForSyncCalled; 

     protected override void ValidateForSyncCall() 
     { 
      ValidateForSyncCalled = true; 
      throw new ExceptionToTerminateTest(); 
     }     
    } 


    [TestMethod] 
    public void CalculationService_Calculate_Sync_Calls_ValidateForSyncCall() 
    { 
     InitializeMocks(); 
     TestCalculationService calculationService = new TestCalculationService(); 
     calculationService.MessageInstanceFactory = _mockMessageInstanceFactory; 

     try 
     { 
      calculationService.Calculate(null); 
      Assert.Fail("Exception should have been thrown"); 
     } 
     catch (ExceptionToTerminateTest) 
     { 
      //ok 
     } 

     Assert.IsTrue(calculationService.ValidateForSyncCalled); 
    } 

回答

3

如果可以成功地隔離測試的方法的部分,則該方法的該部分應該是在其自己的一個較小的方法的候選者。我更喜歡通過對模擬對象進行重構來更小的方法來中止方法,或者更糟糕的是修改實際的代碼以瞭解測試。

0

我不擔心對速度的影響 - 它會很小。

雖然我不認爲這是好的做法。主要是因爲如果您專門添加客戶端代碼以促進測試(而不是將您的類設計爲可測試),這總是一個不好的跡象。您測試的方法是否可能過多?如果您在測試中保留方法的好處,那麼這段代碼本身應該是一種方法嗎?

我也想知道如何在運行時避免異常。如果你開始有這樣的代碼:

if (IsTesting) 
{ 
    throw new TerminateTestException(); 
} 

然後參數可以提出,要測試的代碼是實際獲取運行的代碼不同。在那種情況下,你真的在​​測試什麼嗎?

而且一個,最後,心想:我認爲您是至少一個測試用例(運行全部通過測試案例的方式,或以確保例外的情況下設置了所有的嘲笑不拋出時不應該)。如果你這樣做了,也許你在測試類本身中缺少一些重構可能性。您不需要爲每個測試單獨建立模擬對象。

0

在我看來,你會更好的提取這段代碼到自己的方法和測試。它被稱爲Sprout方法