处理异常的单元测试

时间:2017-02-27 13:36:32

标签: c# unit-testing

这就是我在代码中所拥有的:

function myMethod()
{
    foreach(var file in files)
    {
        if (noMatch)
        {
            //
            SendEmailAndStopProcessing();
            continue;
        }
        doSomething();
    }
}

我有一个csv文件,它有多行,如果与db值匹配,我会处理它们。

我想创建一个单元测试,确认如果找到noMatch,那么将发送电子邮件并且doSomething将不会被执行。我在这里没有例外,因为没有必要,它通过发送电子邮件来处理(这些是业务规则)。但是,我需要创建一个单元测试来确认是否处理了这种情况。我该怎么处理?如果有异常,我会在我的测试方法中添加预期异常的属性,但由于没有,我被卡住了。

2 个答案:

答案 0 :(得分:1)

在SendEmailAndStopProcessing()中发送电子邮件的任何功能都应该被拉出到一个接口(IEmailSender或其他东西),允许你通过你的类的构造函数注入该接口。

一旦你有了这个,你可以使用Moq或其他一些模拟框架,用一个实际上不会发送电子邮件的存根替换IEmailSender实现。通过这些,您通常可以对方法的调用次数进行断言(如果有的话),所以如果您使用Moq(例如),则可以这样做。

emailMock.Verify(x => x.SendEmail(),Times.Once)

如果未调用SendEmail,哪个会失败。你也可以为你的OrSomething方法做类似的事情。

关键是将组件隔离到接口中,以便可以使用Liskov替换原则随意换出它们。

答案 1 :(得分:0)

正如Kritner所说:创建一个SendEmailAndStopProcessing的模拟并计算它被调用的频率。这当然假设SendEmailAndStopProcessing可以被模拟(方法可以从测试类访问,并且可以被覆盖)。

例如使用Moq

using Moq;

// ARRANGE
var serviceMock = new Mock<MyService>();
serviceMock.Setup(s => s.SendEmailAndStopProcessing()).Verifiable();
// ACT: call myMethod()
// ASSERT
const int expectedNumberOfCalls = 1;
serviceMock.Verify(x => x.SendEmailAndStopProcessing(), Times.Exactly(expectedNumberOfCalls));