一、伪对象
1、简单的业务场景
有一个文件监控程序,有一个方法用来检查文件名的合法性,检查过程中,如文件名不合法,需调用远程web服务记录日志,如远程web服务调用发生异常,发送邮件到指定收件人(类似这句话描述的业务场景在实际开发中数不甚数)。
2、什么是伪对象
上面所举的业务场景,文件监控主体程序是需要自己实现的,而远程web服务以及邮件服务都是监控程序所依赖的外部服务,在我们开发测试的时候可能还不能直接调用,或者调用服务代价太大(想想为什么代价比较大?),这个时候我们如何进行测试呢?
答案是构造伪对象(fake object)来代替外部依赖的服务,伪对象就是桩对象和模拟对象的统称。
在我们这个业务场景中,显然需要构造两个伪对象,即最常用的两个基础服务:日志和邮件服务。
(1)桩对象(stub)
定义:桩对象是对系统中现有依赖项的一个替代品,可人为控制,通过使用桩对象,无需涉及依赖项,即可直接对代码进行测试。
和被测试对象的关系:
从上图可知,桩对象在单元测试中是不会被下断言的。
(2)模拟对象(mock)
定义:模拟对象用来决定一个单元测试是通过还是失败。它通过验证被测试对象和伪对象之间是否进行预期的交互来判断。
和被测试对象的关系:
从上图可知,模拟对象在单元测试中必然要被下断言。
综上所述,我们可以分析在当前所举的场景中,如果不对web服务伪对象验证测试结果(即不对它进行断言),而只是用来确保测试正确运行,那么日志服务就是一个桩对象;如果我们需要针对邮件服务来做断言,验证它是否被正确调用,那么邮件服务就是一个模拟对象。
下面就手动创建两个伪对象,其中日志服务为桩对象,邮件服务为模拟对象,代码如下:
a、LogService
using System; namespace MonitorService /// <summary> public class StubLogService : ILogService /// <summary> |