博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
单元测试(二)-桩对象
阅读量:5877 次
发布时间:2019-06-19

本文共 1256 字,大约阅读时间需要 4 分钟。

hot3.png

在单元测试时,难免会碰到一些外部依赖,外部依赖是指在系统中代码与其交互的对象,而且无法对其做人为控制,比如文件系统、线程、内存、时间、数据库结果集等,这时可以使用伪对象(fake)来替代外部依赖,桩对象(stub)便是其中之一

 

一 桩对象

a) 桩对象是对系统中现有依赖项的一个替代品,可人为控制。通过使用桩对象,无需涉及依赖项,即可直接对代码进行测试。使用桩对象可以轻松地控制模拟依赖项的返回值会行为(比如模拟内存溢出异常)。

b) 使用桩对象的前提是要找到原系统中的接缝(Seam)。接缝是指代码中可以插入不同功能(如桩对象类)的地方。有时需要通过重构来制造接缝并解除依赖的方法,可以抽取接口来制造接缝,这样底层实现就可以被替换了。

 

 

二 替换底层实现的方法

 

常用的替换底层实现的方法有:

在构造函数中接收一个接口实现(构造函数注入)

在属性中接收一个接口实现(属性注入)

在方法的参数中接收一个接口实现(参数注入)

使用工厂方法产生接口实现

 

a) 在构造函数中接收一个接口实现

如果要使用类LogAnalyzer中的IsValidLogFileName方法来判断文件名是否有效,在生产环境下,IsValidLogFileName方法要读取配置文件,然后根据配置内容来进行判断,这个方法依赖文件系统。重构过程如下:

抽取IExtensionManager

 

 

通过构造函数传递IExtensionManager的实现,判断文件名是否有效交给IExtensionManager.IsValid来做

 

 

在测试代码中,构造伪对象FakeExtensionManager并传递给LogAnalyzer

 

 

伪对象FakeExtensionManager是可控的

 

 

b) 属性注入和参数注入与构造函数注入的实现方法是类似的,但通过构造函数或参数注入意味着参数是必须的,而属性注入却是可选的,所以使用属性注入时要注意默认注入的处理。

 

c) 使用工厂产生接口实现

在工厂类中,Create()方法默认返回生产环境的FileExtensionManager,测试代码可以通过SetManager传递伪对象

 

 

LogAnalyzer通过Create方法取得IExtensionManager的接口实现

 

 

在测试代码中,调用ExtensionManagerFactory.SetManager(**)注入FakeExtensionManager伪对象

 

 

d) 除了上述方法,还有很多方法可以达到解除依赖的目的,比如基类、重写等方式。但不管哪种方法,为了测试而重构可能会破坏一些面向对象的基本原则,比如封装。这就需要努力在可测试性和封装之间取得平衡,虽然这比较困难,但保证可测试性也是很重要的。

 

参考资料:

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

 

转载于:https://my.oschina.net/u/2327858/blog/907765

你可能感兴趣的文章
Python3之多线程学习
查看>>
aspx页面@Page指令解析
查看>>
POJ 2002
查看>>
MVC和MTV结构分析
查看>>
每天一个linux命令:mkdir
查看>>
thinkphp总体设计
查看>>
HYPER -V 独立安装的 2016版本 中文版 下载好慢啊
查看>>
最大数maxnumber bzoj1012 JSOI2008 单调队列
查看>>
githua学习地址
查看>>
(转)微信网页扫码登录的实现
查看>>
SpringBoot2.x配置Cors跨域
查看>>
用AJAX实现页面登陆以及注册用户名验证
查看>>
mariadb启动报错:[ERROR] Can't start server : Bind on unix socket: Permission denied
查看>>
nginx的信号量
查看>>
30分钟新手git教程
查看>>
The C Programming Language (2nd Edition)
查看>>
Today extension 与 containing app通信方式
查看>>
设计模式
查看>>
.Net配置文件读取及修改方法封装(未加密)
查看>>
读书笔记--SQL必知必会--常用MySQL(MariaDB)命令及示例
查看>>