Mock 与 Stub

在进行单元测试的时候,我们会发现我们要测试的方法会有很多外部依赖,比如:发邮件,进行网络通讯,操作文件系统等等。而我们通常关注的是被测试对象的功能和行为,对于它的依赖,我们仅仅需要关注它们之间的交互,但对依赖的对象是如何执行的具体细节我们并不关注。较为常见的技巧就是使用mock对象或者stub对象来代替真实的依赖。

Mocks aren’t stubs

这是软件大师Martin Fowler的一篇经典博文。Martin大师在文章中详细的解释了Mock与Stub的区别,以及怎样使用它们进行TDD实践等等一系列干货,强烈推荐阅读,猛击这里阅读原文。我无意把大师的话再复述一遍,所以在本文中我就聊聊我对Mock与Stub的理解以及一些实践。

相同点

先看看两者的相同点吧,非常明确的是,Mock和Stub都可以用来对系统(或者将粒度放小为模块,单元)进行隔离。先看看两者的相同点吧,非常明确的是,Mock和Stub都可以用来对系统(或者将粒度放小为模块,单元)进行隔离。

不同点

Mock和Stub有两个主要区别:

  1. 校验测试结果的方式不同,Mock倾向于校验行为(Beahavior verification),Stub倾向于校验状态;
  2. Mock和Stub也代表了两种将测试与设计结合在一起的理念。

上面的说法比较抽象,让我们通过例子来看看Mock与Stub的区别。

使用Stub进行单元测试

下面是一个使用Stub进行单元测试的例子,我们打算创建一个订单对象,并用仓库中的货物填充这个订单。这个订单对象很简单,只有产品和数量两种信息,仓库保存着不同产品的目录。当我们需要填充订单的时候,会有两种不同的回应,如果仓库中有足够的货物,那么订单就会被填满,并且仓库相应产品的数量就会降低到对应的数量。如果仓库中没有足够的参评,那么订单就不会被填充,并且仓库中产品的数量没有任何的变化。

public class OrderStateTester extends TestCase{ private static String TALISKER = "Talisker"; private static String HIGHLAND_PARK = "Highland Park"; private WareHouse warehouse = new WareHouseImpl(); protected void setup() throws Exception{ warehouse.add(TALISKER , 50); warehouse.add(HIGHLAND_PARK , 25); } public void testOrderIsFilledIfEnoughInWarehouse(){ Order order = new Order(TALISKER , 50); order.fill(warehouse); assertTrue(order.isFilled()); assertEquals(0 , warehouse.getInventory(TALISKER)); } public void testOrderDoseNotRemoveIfNotEnough() { Order order = new Order(TALISKER , 51); order.fill(warehouse); assertFalse(order.isFilled()); assertEquals(50 , warehouse.getInventory(TALISKER)); }}

上面的例子里,我们需要对Order对象进行测试,为了验证Order.fill方法,我们还需要WareHouse对象。但真正的WareHouse对象内部可能有很复杂的实现,比如读取文件,访问数据库,持有同步锁以维持对象在并发访问时内部数据正确等。实际上在单元测试时我们并不需要去和这些代码发生交互,而且这些复杂的代码还会让我们的单元测试很不稳定。数据库连接失败、必须的配置文件读取失败等都会导致我们的单元测试失败。显然我们并不希望这些外部的因素影响我们的单元测试

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏微信公众号:Java团长

从零讲Java,给你一条清晰地学习道路!该学什么就学什么!

主要学习: 1.向量,链表,栈,队列和堆,词典。熟悉 2.树,二叉搜索树。熟悉 3.图,有向图,无向图,基本概念 4.二叉搜索A,B,C类熟练,9大排序熟悉。 ...

1541
来自专栏java架构学习交流

如何用比较快速的方法掌握Spring的核心——依赖注入,Java web轻量级开发面试教程 读书笔记

      我们知道,Java方面的高级程序员一定得掌握Spring的技能,其中包括Spring 依赖注入(IOC),面向切面(AOP),和数据库的整合(比如和...

21210
来自专栏涂小刚的专栏

从 PageRank Example 谈 Spark 应用程序调优

在做PageRank测试时,发现有很多有趣的调优点,想到这些调优点可能对用户来说是普遍有效的,现把它整理出来一一分析,以供大家参考。

1.2K3
来自专栏铭毅天下

干货 |《从Lucene到Elasticsearch全文检索实战》拆解实践

1、题记 2018年3月初,萌生了一个想法:对Elasticsearch相关的技术书籍做拆解阅读,该想法源自非计算机领域红火已久的【樊登读书会】、得到的每天听本...

2K6
来自专栏小特工作室

解决微信公众平台IP白名单

微信公众平台,作为自媒体的旗舰级产品,越来越多的人已经投入它的怀抱。正如它的广告词所说:再小的个体,也有品牌 好吧,闲话不多说,今天要说的是它的IP白名单机制。...

9386
来自专栏更流畅、简洁的软件开发方式

【自然框架】之数据访问 —— 再小的类库也需要设计。

  以前也写过几篇关于数据访问的,这里是最新的总结。麻雀虽小五脏俱全,数据访问也许不起眼,但是也要好好的设计一翻。从2004年开始用自己的数据访问,一直到现在,...

2389
来自专栏函数式编程语言及工具

Akka(28): Http:About Akka-Http

  众所周知,Akka系统是基于Actor模式的分布式运算系统,非常适合构建大数据平台。所以,无可避免地会出现独立系统之间、与异类系统、与移动系统集成的需求。由...

2607
来自专栏Albert陈凯

理解zookeeper选举机制

zookeeper集群 配置多个实例共同构成一个集群对外提供服务以达到水平扩展的目的,每个服务器上的数据是相同的,每一个服务器均可以对外提供读和写的服务,这点...

6565
来自专栏Aloys的开发之路

Python第三方常用工具、库、框架等

       Python ImagingLibrary(PIL):它提供强大的图形处理的能力,并提供广泛的图形文件格式支持,该库能进行图形格式的转换、打印和显...

43210
来自专栏漏斗社区

黑客游戏| Owasp juice shop (一)

0x01 前言 最近看到一篇关于owasp juice shop的文章,觉的很有意思,斗哥就自己撸了个环境,上手后深深觉的这是一个很棒的漏洞靶场,所以就把该...

4888

扫码关注云+社区

领取腾讯云代金券