【问题标题】:How to simulate throwing an exception in Unit tests?如何在单元测试中模拟抛出异常?
【发布时间】:2012-01-13 13:51:52
【问题描述】:

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

我希望能够 100% 覆盖我的代码,但我无法测试可能出现异常的代码。例如,我无法模拟可能发生的电源故障。

例如:

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

我希望能够模拟此方法中应捕获的任何类型的异常。
有没有图书馆可以帮助我解决这个问题?

编辑 1: 对完成我对 Moq 提出的要求有任何帮助吗?

【问题讨论】:

  • 您的代码示例并不能真正解释您的问题。为什么不能模拟电源故障?您是否试图“注入”会导致上述异常被抛出的条件?真正的问题是什么?
  • 是的,就像在 stackoverflow.com/a/8851628/79379 中一样,但没有我为了模拟数据库故障而破坏数据库。

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


【解决方案1】:

您需要创建一个模拟对象来代替可以引发这些异常的真实对象。然后你可以创建简单的类似这样的测试:

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

如果您使用的是依赖注入框架,它可以更轻松地用模拟代码替换真实代码。

【讨论】:

    【解决方案2】:

    您需要的是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
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-11-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-07-08
      • 1970-01-01
      相关资源
      最近更新 更多