如何模拟在单元测试中抛出异常?

时间:2012-01-13 13:51:52

标签: c# unit-testing exception c#-4.0 exception-handling

如何模拟C#单元测试中抛出的异常?

我希望能够100%覆盖我的代码,但我无法使用可能发生的异常来测试代码。例如,我无法模拟可能发生的权力法则。

例如:

public void MyMethod()
{  
  try
  {  
  ...  
  }  
  catch(OutOfMemoryException e)
  {
  ...
  }  
  catch(RandomErrorFromDatabaseLayer e)
  {
  ...
  }  
}

我希望能够模拟此方法中的任何异常并且应该被捕获 是否有任何图书馆可以帮助我解决这个问题?

编辑1:   有没有帮助我完成我对Moq的要求?

2 个答案:

答案 0 :(得分:9)

您需要创建一个模拟对象,代表可以抛出这些异常的真实对象。然后你可以创建类似这样的测试:

public void ExampleMethod()
{
    throw new OutOfMemoryException();
}

如果您正在使用依赖注入框架,则可以更轻松地使用模拟代码替换实际代码。

答案 1 :(得分:7)

您需要的是stub - 一个可以模拟代码某些条件的对象。出于测试目的,通常用stub(或其他类型的伪对象)替换实际对象实现。在您的情况下,请考虑:

public class MyClass
{
    private IDataProvider dataProvider;

    public void MyMethod()
    {
        try
        {
            this.dataProvider.GetData();
        }
        catch (OutOfMemoryException)
        {
        }
    }
}

现在,您正在测试的类应该可以在某个级别进行配置 - 这样您就可以在测试时轻松替换真实的DataProvider实现与存根/伪造的实现(就像您说的那样,您不想破坏您的数据库) - 没人要!)这可以通过构造函数注入(或实际上任何其他dependency injection技术)来实现。

然后你的测试是微不足道的(测试异常时需要测试的一些要求):

[Test]
public void MyMethod_DataProviderThrowsOutOfMemoryException_LogsError()
{
    var dataProviderMock = new Mock<IDataProvider>();
    dataProviderMock
        .Setup(dp => dp.GetData())
        .Throws<OutOfMemoryException>();
    var myClass = new MyClass(dataProviderMock);

    myClass.MyMethod();

    // assert whatever needs to be checked
}