由于一直没有完全搞明白Mock和Stub的区别,所以查了很多文章,而这一篇是做好的:

http://yuan.iteye.com/blog/470418

尤其是8楼,Frostred的发言,描述地相当清楚具体,转帖到此,以作日后的参考:

很高兴前面的一点文字能对你有所帮助。事实上,写东西时候,也是对自己的思想整理和精炼的过程,所以可以说是互相帮助吧。你要是有什么疑问或不同意见,可以指出来,我们可以再深入探讨。
好了,下面说说我对Mock/Stub区别的看法。
首先,我想再强调一下使用Mock/Stub的目的,那就是,去代替那些被测试代码所依赖的,但不可信赖东西。不管这些东西是什麽,当然最终表现出的还是class。 如class BlogDao, 它不可信赖是因为它访问数据库,class ConfigReader, 它不可信赖是因为它访问配置文件。class MyStringParser, 它不可信赖是因为它有很多逻辑,而且还没有对它进行足够的测试。当然,如果你对它进行足够的测试,你也可以认为它可以信赖。例如,你有一个class MyStringProcessor, 它用到了MyStringParser, 当你测试MyStringProcessor 时,你就有选择是隔离MyStringParser 还是不隔离。注意这一选择是建立在你是否认为MyStringParser 可以信赖的基础上,而不是创建的成本是否很高的基础上。当然,在现实生活中,创建的成本高,往往意味着它用到了外部资源,而用到外部资源也就意味着它不可信赖,也就是它必须被隔离。这也是很多人误以为“创建的成本是否很高”就是判断是否需要隔离的条件。
以上又废了好多话强调使用Mock/Stub的目的,不过我一直认为理解目的是最重要的,目的理解了,其它就容易明白了。
Back to Mock/Stub, 不知你注意了没有,我一直没用Mock这个词做动词,我用的是“代替”或 “隔离”,在这里“代替”和“隔离”是一个意思 。(“隔离”或许更准确些,但“代替”更容易理解,而Mock(动词)是一可非常不准确的词)。那么我们用什么来代替或隔离呢?答案是,Stub / Mock objects。那么,为什么会有Stub / Mock 的区别呢。这是因为Stub / Mock 在测试中扮演的角色有细微的差别,这一差别其实又取决于“被隔离对象”在“被测试对象”里扮演角色的差别(对不起写得有点绕嘴,希望你能看明白)。
其实,分得细点,不只有Stub / Mock,还有其它类型。如,在 xUnit Test Patterns 这本书里,它把这类对象统称为Test Double(因为stunt double 在电影里是替身的意思)。具体的类型有
• Dummy Object
• Test Stub
• Test Spy
• Mock Object
• Fake Object
其中,Fake Object是指一个假的(相对于现实要用到的),但完整的实现。如, InMemoryBlogDao,相对于 SqlBlogDao,它不真的访问数据库,但它是一个对 BlogDao 接口 的完整实现。
其他的类型,我认为,Dummy Object,Test Stub,Test Spy基本可以归为Stub,剩下的Mock Object 当然是Mock。
首先看Dummy Object,测试代码需要Dummy Object是因为有了它才能通过编译,测试才能跑起来,但其实测试中可能根本就用不到它。例如,创建BlogService 需要 BlogDao,但你可能测试BlogService 的一个方法,它根本就没用到BlogDao。此时,你可以用 new BlogService(new NullBlogDao()),  NullBlogDao 就是Dummy Object,因为它的存在只是为了通过编译,它根本就不参与测试。
Test Stub 参与测试, 但你不在乎它是何时何地以何种方式参与测试的,它的存在是为了让测试跑起来。非常常见的情况是你需要它提供一些返回值。例如,你可以用HttpContextStub 来代替真正的HttpContext, 用它提供例如SessionId, ResquestParameter 之类的值。你的测试可能会用到这些值,但你不会去验证是不是getSessionId() 被调用了,更不会去验证它是何时何地以何种方式被调用的。
Test Spy 不但参与测试,你还要验证它的参与产生了某种结果。如BlogService 例子。你可以定义一个TestSpy:
public class BlogDaoTestSpy implements BlogDao {
public Blog savedBlog = null;
public void save(Blog blog) {
savedBlog = blog;
}
}
那么你的测试可写成这样:
@Test 
public void testSaveBlog(){ 
Blog blog = new Blog();   
blogService.save(blog); 
assertEqual(blog, ((BlogDaoTestSpy)blogDao).savedBlog);

注意,在测试中我们验证了blogService.save(blog) 会导致blogDao的savedBlog 产生变化,但我们不去验证blogDao是以何种形式参与测试而导致这一变化的。
下面终于该Mock Object 出场了,事实上,你的测试就是很好的Mock例子。在测试中,你验证了如果blogService.save(blog) 被调用,blogDao的save(blog) 一定也会被调用,而且被调用时,参数一定是 blog。也就是说,你验证了blogDao必须以这种特定的形式参与测试。
通过比较,我们可以看到,从Dummy Objec到 Mock Object,测试代码对TestDouble 的要求越来越强,验证的内容也越来越强。这种强制约有好处也有坏处,不过,总的来说,我们希望够用就行。换句话来说,如果能验证代码的正确性,如果Stub够用,就不要用Mock,因为Stub比Mock简单,Stub 对被测代码的制约也小的多,所以被测代码改起来也更容易。
为什么有些时候必须用Mock呢?一个常见的情况是需要参与的方法没有返回值。例如blogDAO.save(blog)。首先,我想说的是,这行代码非常重要,是一定要测试到的。不然的话,你把这行从BlogService中删掉,都没有测试报错,这显然不对。问题是blogDAO.save(blog) 没有返回值,我们怎么才能知道它被正确调用了呢。当然,我们可以用TestSpy,象上面的例子。不过,一般的Dynamic Mock framework 都不支持象上面那类的TestSpy,所以你要手写TestSpy。如果你不愿手写,我认为用Mock是完全可以接受的。这里我还想说的是,它没有“深入到DAO的接口设计中去了”, 因为你的测试只是验证blogDao的save(blog) 会被调用,而没有验证save(blog)的结果是不是正确。如果你验证save(blog)的结果是不是正确,那才是“深入到DAO的接口设计中去了”。所以总的来说,我认为你用Mock 测试是perfectl valid。一点小毛病是,在测试中,你没必要去setTitle("title"), setContent("content"),setCreatedTime(new Date()),这些跟你要测的东西没有任何关系。
一些comments:
“测试代码本来只需要知道传什么参数给Service,并且预期测试Service返回什么值就够了,管它DAO调用什么方法干嘛?”
--理想情况下是,问题是, Service没有返回值,更讨厌的是,连DAO都没有返回值,我们有不能让它沉到太平洋里去,那怎么测试,只好用没办法的办法,验证blogDao的save(blog)将 被调用。
“整个Service的实现对测试代码应该是不可见的“
--理想情况下是,现实中常常不是,尤其是Service class 自己没什么逻辑,but just some interaction with other classes. 例如,Service class 接受一个DTO参数, 然后,用Mapper 把它Map 成Entity object,用Validator 去 validate, 用 logger 写 一个 log, 最后用DAO 存到数据库。这种情况下,你不得不做一些基于Mock 的Interactive 测试。
最后,我的观点,
• 尽量少用 Mock
• 该用Mock的时候就用,Mock没什么可怕的
• 明白测试的目的是最重要的

如果参见这篇博文的人想知道更多,或者英文足够好,这篇老外写的文章,非常地不错:

http://martinfowler.com/articles/mocksArentStubs.html,Mocks Aren't Stubs.

文章来源:http://blog.csdn.net/lilybear101/article/details/6938646

[转]软件测试- 3 - Mock 和Stub的区别的更多相关文章

  1. Mock 或 Stub 有什么区别?

    存根 一个有助于运行测试的虚拟对象. 在某些可以硬编码的条件下提供固定行为. 永远不会测试存根的任何其他行为. 例如,对于空堆栈,您可以创建一个只为 empty()方法返回 true 的存根.因此, ...

  2. 软件测试 -- 测试人员和QA的区别

    软件测试人员的职责是尽可能早的找出软件缺陷,确保得以修复. 而质量保证人员(QA)主要职责是创建或者制定标准和方法,提高促进软件开发能力和减少软件缺陷. 测试人员的主要工作是测试,质量保证人员日常工作 ...

  3. Mock和injectMocks的区别

    @Mock private ForeCatalogManageServiceImpl foreCatalogManageServiceImpl; 如果是上面的写法,那么 红框方法里面的代码不会执行,这 ...

  4. @Mock与@InjectMocks的区别

    @Mock: 创建一个Mock. @InjectMocks: 创建一个实例,简单的说是这个Mock可以调用真实代码的方法,其余用@Mock(或@Spy)注解创建的mock将被注入到用该实例中. 注意: ...

  5. Stub和Mock的理解

    我对Stub和Mock的理解 介绍 使用测试驱动开发大半年了,我还是对Stub和Mock的认识比较模糊,没有进行系统整理. 今天查阅了相关资料,觉得写得很不错,所以我试图在博文中对资料进行整理一下,再 ...

  6. 我对Stub和Mock的理解

    介绍 使用测试驱动开发大半年了,我还是对Stub和Mock的认识比较模糊,没有进行系统整理. 今天查阅了相关资料,觉得写得很不错,所以我试图在博文中对资料进行整理一下,再加上一些自己的观点. 本文是目 ...

  7. 原!!关于java 单元测试Junit4和Mock的一些总结

    最近项目有在写java代码的单元测试,然后在思考一个问题,为什么要写单元测试??单元测试写了有什么用??百度了一圈,如下: 软件质量最简单.最有效的保证: 是目标代码最清晰.最有效的文档: 可以优化目 ...

  8. C# Rhino Mocks

    Mock和Stub的区别: 1,Stub是一个在你的测试代码中需要用到的object,你可以为它设置expectations,然后它就会按其运行,但是这些expectations不会被核对. 2,Mo ...

  9. EasyMock入门

    这是一个JavaProject,有关EasyMock用法详见本文测试用例 首先是用到的实体类User.java package com.jadyer.model; public class User ...

随机推荐

  1. ffmpeg的新东东:AVFilter

    http://blog.csdn.net/niu_gao/article/details/7219641 利用ffmpeg做图像的pixel format转换你还在用libswscale吗?嘿嘿,过时 ...

  2. angularJS 状态样式绑定

    angularJS提供输入框不同状态下的样式绑定 输入框有4种状态 ng-model 指令可以为应用数据提供状态值(invalid, dirty, touched, error): <!DOCT ...

  3. pandas知识点汇总

    ## pandas基础知识汇总 1.时间序列 import pandas as pd import numpy as np import matplotlib.pyplot as plt from d ...

  4. discuz 安装 文件不可写

    discuz安装过程中,系统会自动检查环境及文件目录权限,当出现目录不可写: 这个时候只需要用ftp修改文件夹权限就可以了

  5. Oracle学习-Power Designer、visio 2003、Oracle sql developer、OEM、expdp

    Oracle的体系太庞大了.对于刚開始学习的人来说,难免有些无从下手的感觉. 经过一学期的学习对Oracle学习有了一些深入的了解,由于之前学习过Oracle的一些主要的知识.所以学习起来上手比較快一 ...

  6. linux文本分析利器awk

    转 快速理解linux文本分析利器awk 原文链接 杜亦舒 性能与架构 awk是什么 如果工作中需要操作linux比较多,那么awk是非常值得学习的 awk是一个极其强大的文本分析工具,把文件逐行的读 ...

  7. 高性能Web架构

    高性能Web架构 转自 架构文摘 2017-02-07 王杰  引言 最新中国互联网络信息中心(CNNIC)发布的<第38次中国互联网络发展状况统计报告>,2016年6月,我国网民规模达7 ...

  8. JavaScript正则表达式基础知识汇总

    一.创建正则对象: 1.构造函数RegExp创建正则对象 var pattern = new RegExp('s$'); //pattern匹配以s结尾的字符串 2.使用正则直接量 var patte ...

  9. NGUI ScrollView中MoveRelative,Scroll的区别

    Scroll会计算边界,和直接拖拽的效果类似 MoveRelative不计算边界,超出边界了也不会管,也不会应用缓动效果

  10. atitit.浏览器web gui操作类库 和 操作chrome浏览器的类库使用总结

    atitit.浏览器web gui操作类库 和 操作chrome浏览器的类库使用总结 1. 常见标准 1 1.1. 录制重放 1 1.2. 一个窗体一个proxy cookie 1 1.3. exec ...