单元测试-隔离框架NSubstitute

Posted zhixin9001

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了单元测试-隔离框架NSubstitute相关的知识,希望对你有一定的参考价值。

之前学习了单元测试的基础知识,以及桩对象和模拟对象的不同作用。但在实际应用中,往往不会直接手写桩对象或者模拟对象,而是使用隔离框架动态的创建这些对象,这可以让测试变得更简便、快捷,还可以更好地应对复杂的测试。这里学习的便是隔离框架的一种——Nsubstitute。

 

一 开始使用NSubstitute

在前面有一个测试场景为:使用LogAnalyzer.Analyze方法分析文件,如果文件名过短,就记录日志,为了测试LogAnalyzer类与ILogger实现之间的交互,需要手写一个实现了ILogger接口的模拟对象,并针对这个模拟对象进行断言。那么现在使用NSubstitute来进行这一过程,测试代码只有下面几行就可以做到了。

 

logger就是使用NSubstitute创建的模拟对象。Substitute静态类动态负责创建伪对象,For 方法是产生伪对象的基本方法。最后一句中的logger.Receive方法在接口中并不存在,而是被NSubstitute扩充的,用于验证方法是否被调用。logger.Received().LogError("Filename too short:a.txt")整体的意思便是:测试logger对象是否Receive对LogError方法的调用请求,而且传递的参数为"Filename too short:a.txt"。这是对模拟对象的测试方法。

 

 


 

二 设置伪对象的返回值

还可以设置方法在一定条件下的返回值

a) 全匹配

 

rule.IsValidLogFileName("a.txt").Returns(true),指定了当方法IsValidLogFileName()被调用且参数为"a.txt"时返回结果为true

 

b) 类型匹配

 

rule.IsValidLogFileName(Arg.Any<string>()).Returns(true),指定了当方法IsValidLogFileName()被调用且参数为string类型时返回结果为true,这样匹配的范围会更广,这种指定方法也最常用。类型匹配主要使用Arg来指定

 

c) 返回异常

 

还可以指定方法在一定的条件下返回何种异常,比如这儿的代码中指定的条件为IsValidLogFileName()被调用且参数为string类型时,返回Exception("fake exception")。这儿的写法与前面的有点区别,用到了lambda表达式

 

 


 

 

三 使用隔离框架的注意事项

a) 隔离框架的写法会使代码可读性降低

b) 明确要验证的对象,不要验证错误的事情,也不要过度验证

c) 尽量少用模拟对象,一个测试中最多出现一个模拟对象,但模拟对象存在时,要针对模拟对象进行断言

d) 不要使用桩对象来验证交互,这是模拟对象做的事情

 

参考资料:

The Art of Unit Testing with examples in C#, 2nd Edition by Roy Osherove

 

以上是关于单元测试-隔离框架NSubstitute的主要内容,如果未能解决你的问题,请参考以下文章

在单元测试中验证函数调用顺序

测试篇——初探单元测试

单元测试系列

单元测试框架选择

如何对 ServiceStack 进行单元测试?

代码质量保证-单元测试框架pytest