以前学习了单元测试的基础知识,以及桩对象和模拟对象的不一样做用。但在实际应用中,每每不会直接手写桩对象或者模拟对象,而是使用隔离框架动态的建立这些对象,这可让测试变得更简便、快捷,还能够更好地应对复杂的测试。这里学习的即是隔离框架的一种——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"时返回结果为truestring
b) 类型匹配it
rule.IsValidLogFileName(Arg.Any<string>()).Returns(true),指定了当方法IsValidLogFileName()被调用且参数为string类型时返回结果为true,这样匹配的范围会更广,这种指定方法也最经常使用。类型匹配主要使用Arg来指定io
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