前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >可测试性系列之测试替身Test Double

可测试性系列之测试替身Test Double

作者头像
码农戏码
发布2022-06-07 18:35:30
7270
发布2022-06-07 18:35:30
举报
文章被收录于专栏:DDD

在做程序测试时,常会用到测试替身来协助我们快速完成测试。

有时候被测试系统(system under test(SUT))很难测试,因为在测试环境下依赖的组件不能正常使用。如外部系统。

当在一个不能使用真实依赖组件(depended-on component(DOC))的地方写test时,我们可以使用Test Double[1]。

Test Double

Test Double概括起来,有以下几种:

Martin Fowler在Mocks Aren't Stubs [2]中给出解释:

Martin Fowler解释的还不是太明白,我又收集了更明白一点的解释[3]:

•Dummy - just bogus values to stisfy the API

Example: If you're testing a method of a class which requires many mandatory parameters in a constructor which have no effect on your test, then you may create dummy objects for the purpose of creating new instances of a class.

•Fake - create a test implementation of a class which may have a dependency on some external infrastructure. (It's good practice that your unit test does NOT actually interact with external infrastructure.)

Example: Create fake implementation for accessing a database, replace it with in-memory collection.

•Stub - override methods to return hard-coded values,also refered to as state-based

Example:Your test class depends on a method calculate() taking 5 minutes to complete.Rather than warit for 5 minutes you can replace its real implementation with stub that returns hard-coded values;taking only a small faction of the time.

•Mock - very similar to Stub But interaction-based rather than state-based.This means you don't expect from Mock to return some value,but to assume that specific order of method calls are made.

Example:You're testing a user registration class.After calling save,it should call send ConfirmationEmail.

上面的解释已经很明白了,简单总结一下:

Dummy:主要是用来填充参数,以构造需要测试的对象

Fake:简单模拟实现,如Dao,但只是空实现

Stub:相对fake多了点硬编码返回值,两者很相似

Mock:相对状态验证更多的是行为验证

阅读到这儿大概率已经明白了,也就fake与stub还有点模糊,要想明白更清晰的区别,需要先了解一下生命周期和验证方式:

1、生命周期

每个测试都是由四个依次执行的阶段:

初始化(SetUp)、执行测试(Exercise)、验证结果(Verify)和复原(Teardown)

2、验证方式

在验证阶段,通常有两种验证方式:状态验证与行为验证

状态验证:

代码语言:javascript
复制
//肯定会使用的assert
assertEquals(expected,actual);

行为验证:

代码语言:javascript
复制
//Mockito中的verify
verify(mock, times(3)).do();

徐昊老师有个生动的描述:

万恶淫为首,论迹不论心,论心世上少完人;不关心过程,只看结果。结果验证

百善孝为先,论心不论迹,论迹贫家无孝子;看重过程,不看重结果。行为推断

所以我们判断淫棍总比判断孝子准确


测试策略是要保证有效性的同时,尽可能降低测试成本。

fake、stub、spy、mock 以此排序,成本越来越低,同时有效性也越来越低。

spy与mock在使用Mockito时能明显感受到它们俩的区别,fake与stub的区别,从上面的定义看,很接近。

徐昊老师引入进程的视角来进一步区分:

跨进程边界是fake,进程之间的stub就是fake。

结合上面的解释明确多了,当使用数据库时,fake一个内存数据库。

以进程划分:

进程间替身:dummy fake spy

进程内替身:stub mock spy

以验证方式划分:

严格来说,我们状态验证使用fake stub,行为验证使用mock。

dummy和spy都不验证,dummy是不能验,spy是还没验。

spy可以按状态(比如回放)也可以按行为(比如对比)验证。

spy已经在行为验证和状态验证的边上。spy是记录调用,对调用加上验证就是mock

如果用记录来reply就是录播测试,比如你在两个系统间做了spy,把请求和结果播放出来,这样相当于用spy的数据做了stub。

把请求结果和目标结果做对比,实际相当于拿spy数据做了mock

spy本身只取数据不验证,但是正常的doc内部数据不可知,因而spy是一种替身技术,并不是验证技术。

spy is dumb mock

总结

测试策略是要保证有效性的同时,尽可能降低测试成本。因此Test Double是SUT中测试中不可或缺的,Test Double的形式有dummy fake stub spy mock,以进程维度与验证方式维度能更好地区分它们。

References

[1] Test Double: http://xunitpatterns.com/Test%20Double.html [2] Mocks Aren't Stubs : https://martinfowler.com/articles/mocksArentStubs.html [3] 收集了更明白一点的解释: https://code-examples.net/en/q/34c8d7

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2022-04-18,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 码农戏码 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Test Double
  • 总结
    • References
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档