抛出异常后的单元测试行为?

时间:2010-07-18 11:44:36

标签: unit-testing exception-handling tdd nunit rhino-mocks

我刚刚开始进行单元测试并且有一个场景我不知道如何评估并且我的解决方案感觉不对。

我有一些代码可以执行某些操作,如果它失败,即抛出异常,异常被捕获并记录如下。

 public T CreateTypedObjectInstance<T>()
 {
     T o = default(T);
     try
     {
         o = Activator.CreateInstance<T>();
     }
     catch (Exception ex)
     {
         LogError(ex);
         throw ex;
     }
     return o;
 }

 private void LogError(Exception ex)
 {
     if (logger != null)
     {
        logger.LogError(ex);
     }
 }

我想测试一下,如果抛出错误,它会调用LogError()方法,后者又会调用另一个对象。

我已经使用了一个用于记录器的模拟来接近它,并捕获抛出的第一个异常,然后断言调用了LogError方法。但是,这不需要捕获异常吗?我记得读过一些在测试中尝试捕获的东西是不好的吗?有没有其他方法可以执行此测试,还是应该重构逻辑?任何想法都会很棒!

      [Test]
    public void CreateTypedObjectInstance_GivenTypeWithoutPrivateContructor_LogErrorToLogger()
    {
        //Setup Method used
        MockRepository mockery = new MockRepository();
        ILogger mockedLogger = mockery.StrictMock<ILogger>();
        genericObjectFactoryInstance.Logger = mockedLogger;
        Expect.Call( delegate { mockedLogger.LogError(null); } ).IgnoreArguments();
        mockery.ReplayAll();
        // this will throw an error as String does not have a parameterless constructor
        try
        {
            genericObjectFactoryInstance.CreateTypedObjectInstance<String>();
        }
        catch { /*ignore this error to test behaviour after*/ }
        mockery.VerifyAll();
    }

修改

使用Mark Rushakoff回答测试成为一种魅力。

        [Test]
    public void CreateTypedObjectInstance_GivenTypeWithoutPrivateContructor_LogErrorToLogger()
    {
        //Setup Method used
        MockRepository mockery = new MockRepository();
        ILogger mockedLogger = mockery.StrictMock<ILogger>();
        genericObjectFactoryInstance.Logger = mockedLogger;
        Expect.Call( delegate { mockedLogger.LogError(null); } ).IgnoreArguments();
        mockery.ReplayAll();
        Assert.Throws<MissingMethodException>(() => genericObjectFactoryInstance.CreateTypedObjectInstance<String>());
        mockery.VerifyAll();
    }

3 个答案:

答案 0 :(得分:7)

您没有说明您正在使用的NUnit版本,但首选方法是Assert.Throws方法。

Assert.Throws<YourCustomException>(() => GenericObjectFactoryInstance.CreateTypedObjectInstance<String>());
当您的测试框架没有提供检查抛出异常的工具时,

@Bruno's answer是合适的。

答案 1 :(得分:2)

单元测试实际上可以检查在满足异常条件时是否抛出异常。例如:

方式:

public int getCalc(int a, int b) throws SampleException {
   if (a > b) {
      throw new SampleException();
   }
   // (..)
}

<强>测试

public void testGetCalcException() {

   try {
     getCalc(2,1); // 2 > 1  exception is expected
     fail("SampleException was expected but was not thrown");       

   } catch(SampleException e) {
      // great - test passed!
   } 

}

答案 2 :(得分:0)

如果您使用NUnit作为您的ut测试框架,您可以使用ExpectedException attibute来检查该方法是否实际抛出了预期的异常。这种方法不要求您尝试在测试代码中捕获块。

您可以查看以下示例以获取更多详细信息 ExpectedException example