单元测试之破除依赖
作者:网络转载 发布时间:[ 2015/12/17 11:48:54 ] 推荐标签:软件测试 单元测试
4:依赖注入(在被测试的单元中注入一个伪实现)
4.1:构造参数注入
顾名思义是实例化的时候在构造参数的时候把伪对象注入
此时我们要修改我们上面的类了如下
被测试类
public class UserBll
{
private readonly IUser _user;
public UserBll(IUser user)
{
this._user = user;
}
public bool IsExistUser(string userId)
{
return _user.IsExist(userId);
}
}
测试代码
[Test]
public void IsExistUser_ExistUser_ReturnsTrue()
{
var fackUser = new FackUser {WillBevalid = true};
var user = new UserBll(fackUser);//注入伪对象
bool result = user.IsExistUser("1");
Assert.IsTrue(result);
}
关于构造函数注入的总结:使用构造函数注入比较简单直观可读性和理解方面也很不错。但是也有问题是当你依赖越来越多的时候,加入构造函数的参数越来越多这样会变得难以维护。
使用场景:比喻api的设计是某些使用者本身是带有参数的构造函数那么可以这么做。
4.2:使用属性(get;set)注入伪对象
被测试类
public class UserBll
{
public IUser User { get; set; }
public UserBll(IUser user)
{
User = new User();//默认的情况执行正常对象
}
public bool IsExistUser(string userId)
{
return User.IsExist(userId);
}
}
代码测试
[Test]
public void IsGetName_NormalGetName_ReturnsTrue() {
var fackUser = new FackUser { WillBevalid = true };
var user = new UserBll { User = fackUser };//属性注入
bool result = user.IsExistUser("1");
Assert.IsTrue(result);
}
关于属性注入总结:和构造函数注入相似不过更易读,更易编写。
什么时候使用属性注入:想表明哪个被测试类的某个依赖项是可选的,或者测试可以放心使用默认创建的这个依赖项,可以属性注入
4.3:在工厂中伪造一个成员(伪对象)
我们先看工厂类
public class UserFactory
{
private IUser _user = null;
public IUser Create()
{
if (_user != null)
return _user;
return new User();
}
[Conditional("DEBUG")]
public void SetUser(IUser muser)
{
_user = muser;
}
}
被测试类
public class UserBll
{
public bool IsExistUser(string userId)
{
var userFactory = new UserFactory();
return userFactory.Create().IsExist(userId);
}
测试代码
[Test]
public void IsGetName_NormalGetName_ReturnsTrue() {
var fackUser = new FackUser { WillBevalid = true };
var userFactory = new UserFactory();
userFactory.SetUser(fackUser);//设置自己要注入的伪对象
bool result = new UserBll().IsExistUser("1");
Assert.IsTrue(result);
}
关于伪造方法的总结: 这种方法很简单,对工厂添加一个你要控制的伪依赖项。对被测试代码没什么改变一切还是原样。
这种方式明显比前两种好。相当于加入了一个工厂的缓冲区。在这里可以做一些逻辑上的处理。
4.4:抽取和重写
使用这种方法的步骤:
在被测试类:
添加一个返回真真实实的虚工厂的方法;
在正常的代码中使用工厂方法
在测试项目中:
创建一个新类
声明这个新类继承被测试类
创建一个你要替换的接口类型的公共字段(不需要属性)
重写虚方法
返回公共字段
在测试代码中:
创建一个存根类的实例。此存根实现所要求的接口
创建新派生类而非测试类的实例
伪造一个工厂方法
public class UserBll
{
public bool IsExistUser(string userId)
{ var user = UserManager();
return user.IsExist(userId);
}
protected virtual IUser UserManager()
{
return new User();
}
创建新类并集成被测试类
public class TestUser : UserBll
{
public TestUser(IUser user) {
_muser = user;
}
private readonly IUser _muser;
protected override IUser UserManager() {
return _muser;
}
}
测试代码:
[Test]
public void IsGetName_NormalGetName_ReturnsTrue() {
var fackUser = new FackUser { WillBevalid = true };//存根实例
var testUser = new TestUser(fackUser);//注入伪对象(新派生的类)
bool result = testUser.IsExistUser("1");
Assert.IsTrue(result);
}
关于抽取和重写注入的总结:写更少的接口,代码更容易替换。我觉得这种方法好,是留了一条路,不光对于测试,如果哪天发现这代码不好了,直接可以在底层新添加一个替换即可,不会影响原来的代码
什么时候使用:当你调用外部依赖项时候想模拟自己想要的值的时候特别受用。
4.5:重构技术变种
先看被测试类
public class UserBll
{
public bool IsExistUser(string userId)
{
return UserManager(userId);
}
protected virtual bool UserManager(string userId)
{
IUser user = new User();
return user.IsExist(userId);
}
}
创建新类并集成被测试类
public class TestUser : UserBll
{
public bool IsSupported;
protected bool IsGetUserName(string userId) {
return IsSupported;
}
}
测试类
public void IsGetName_NormalGetName_ReturnsTrue() {
var testUser = new TestUser { IsSupported = true };
bool result = testUser.IsExistUser("1");
Assert.IsTrue(result);
}
总结:这和上一种方式其实是很像的,只不过这种更彻底。这种方式更加简单。不在添加很多的构造函数,设置方法或者工厂类。不过确实不符合面向对象中的封装原则。暴露了用户不改看到的东西。
各种依赖注入灵活使用。个人觉得后三种都不错。
本文内容不用于商业目的,如涉及知识产权问题,请权利人联系SPASVO小编(021-61079698-8054),我们将立即处理,马上删除。
相关推荐
iOS单元测试mocha、chai、sinon和istanbul实现百分之百的单元测试覆盖率关于单元测试的总结及思考编写更好的Java单元测试的7个技巧Android单元测试框架Robolectric3.0介绍(一)使用Kiwi单元测试总结单元测试如此重要,为什么你不知道Python单元测试??使用装饰器实现测试跳过和预期故障对Controller的单元测试写好单元测试的10个技巧单元测试的重要性Angular单元测试系列??Component、Directive、Pipe 以及ServiceAndroid单元测试的整理提升单元测试体验的利器--Mockito使用总结iOS UnitTest单元测试Vue的单元测试探索(二)
更新发布
功能测试和接口测试的区别
2023/3/23 14:23:39如何写好测试用例文档
2023/3/22 16:17:39常用的选择回归测试的方式有哪些?
2022/6/14 16:14:27测试流程中需要重点把关几个过程?
2021/10/18 15:37:44性能测试的七种方法
2021/9/17 15:19:29全链路压测优化思路
2021/9/14 15:42:25性能测试流程浅谈
2021/5/28 17:25:47常见的APP性能测试指标
2021/5/8 17:01:11热门文章
常见的移动App Bug??崩溃的测试用例设计如何用Jmeter做压力测试QC使用说明APP压力测试入门教程移动app测试中的主要问题jenkins+testng+ant+webdriver持续集成测试使用JMeter进行HTTP负载测试Selenium 2.0 WebDriver 使用指南