2010-05-21 32 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方法