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

rad*_*scu 10 c# unit-testing exception-handling exception c#-4.0

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

我希望能够100%覆盖我的代码,但我无法使用可能发生的异常来测试代码.例如,我无法模拟可能发生的功率损失.

例如:

public void MyMethod()
{  
  try
  {  
  ...  
  }  
  catch(OutOfMemoryException e)
  {
  ...
  }  
  catch(RandomErrorFromDatabaseLayer e)
  {
  ...
  }  
}
Run Code Online (Sandbox Code Playgroud)

我希望能够模拟此方法中的任何类型的异常,并且应该被捕获.
在这件事上有没有可以帮助我的图书馆?

编辑1:完成我向Moq询问的任何帮助?

Chr*_*isF 9

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

public void ExampleMethod()
{
    throw new OutOfMemoryException();
}
Run Code Online (Sandbox Code Playgroud)

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


k.m*_*k.m 7

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

public class MyClass
{
    private IDataProvider dataProvider;

    public void MyMethod()
    {
        try
        {
            this.dataProvider.GetData();
        }
        catch (OutOfMemoryException)
        {
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

现在,您正在测试的类应该可以在某个级别进行配置 - 这样您DataProvider在测试时可以轻松地用存根/伪造的实际实现取代(就像您说的那样,您不想破坏您的数据库 - 没人想要!).这可以通过例如构造器注入(或实际上,任何其他依赖注入技术)来实现.

那么你的测试是微不足道的(一些需要在测试异常时进行测试):

[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
}
Run Code Online (Sandbox Code Playgroud)