How to simulate throwing an exception in Unit test

2020-07-05 05:47发布

How can I simulate an exception being thrown in C# unit tests?

I want to be able to have 100% coverage of my code, but I can't test the code with exceptions that may occur. For example I cannot simulate a power faluire that may occur.

For example:

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

I want to be able to simulate any kind of exception that is in this method and should be caught.
Are there any libraries that may help me in this matter?

Edit 1: Any help in accomplishing what I asked with Moq?

2条回答
啃猪蹄的小仙女
2楼-- · 2020-07-05 06:51

You need to create a mock object that stands in for the real objects that can throw these exceptions. Then you can create tests that simply are something like this:

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

If you are using a dependency injection framework it makes replacing the real code with the mock code much easier.

查看更多
趁早两清
3楼-- · 2020-07-05 06:51

What you need is stub - an object that will simulate certain conditions for your code. For testing purposes, you usually replace real object implementation with stub (or other type of faked object). In your case, consider:

public class MyClass
{
    private IDataProvider dataProvider;

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

Now, class you are testing should be configurable at some level - so that you can easily replace real DataProvider implementation with stubbed/faked one when testing (like you said, you don't want to destroy your DB - nobody wants!). This can be achieved for example by constructor injection (or in fact, any other dependency injection technique).

Your test then is trivial (some made-up requirement to test when exception is thrown):

[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
}
查看更多
登录 后发表回答