前言:单元测试的时候经常出现一个对象依耐另一个你无法控制的对象,所以这个时候你必须去替代成一个你自己可以控制的对象来摆脱依耐。
1:为什么要破除依赖
1.1:运行速度慢
比喻我们要通过用户Id判断用户是否存在,那么我们这个方法就会依赖数据库。这样就成了集成测试,如果大量的测试就会出现速度慢。
1.2:需要配置
由于依赖数据库,就会配置和数据库相关的文件。
1.3:一次性测试很多内容,无法定位错误信息
比喻这个方法错误可能是由于传入的用户Id为空,也可能传入的用户Id不存在,还可能是数据库连接断开等,这样我们就起不到我们单元测试的目的。
2:存根
一个外部依赖项:指的是系统中的一个对象,被测试的代码与这个对象发生交互,但是你不能控制这个对象。比喻前端工程师和后台工程师合作,前端工程师要等待后台返回的数据来处理,那么后台就是他的一个外部依赖项。因为他无法控制后台的代码
定义:一个存根(stub)是对系统中存在的一个依赖项(或协作者)的可控制的替代物(就是你找一个对象来替换你无法控制的对象)。通过使用存根,你在测试代码时无需直接处理这个依赖项。(说白了就是一个你自己定义来对象来取代你无法控制的对象)
3:重构代码设计来提高代码的可测试性
3.1:抽取接口使底层可替换
其实底层我们就应该使用接口,这样上层代码依赖的是接口而不是具体的对象,使项目具有更好的扩展性,当然这里做事为了更好的测试。
从底层方法中抽出一个接口
public interface IUser
{
/// <summary>
/// 检验用户是否存在
/// </summary>
/// <param name="userId">用户名</param>
/// <returns></returns>
bool IsExist(string userId);
}
底层访问数据库的类
public class User:IUser
{
public bool IsExist(string userId)
{
//从数据库查询
//如果有返回true
}
}
待测试的工作单元
public bool IsExistUser(string userId)
{
var user = new User();
return user.IsExist(userId);
}
一个可控制的存根
public class FackUser:IUser
{
public bool WillBevalid = false;
public bool IsExist(string userId)
{
return WillBevalid;
}
}
下面开始注入存根了。