mock.VerifyAll()? NO!

原创 2007年09月22日 00:05:00

TDD我用的很久了,Mock这东西倒没怎么用过。主要是这两年都在写那个nlp的framework,一手一脚搭起来的东西,完全是由底而上,基本需要被交互的interface都有了instance class。也就自然在Junit中写

XXXinterface xxx=new XXXinstance

从而没有必要去面向interface编程了。

最近到了新单位,开始用CAB,遇到了MVC的问题。那种giant view自然不是testable的,在网上搜到了http://codebetter.com/blogs/jeremy.miller/archive/2007/06/04/build-your-own-cab-part-6-view-to-presenter-communication.aspx 的帖子,觉得其中所说的dump view挺符合我的审美观,试着用了用,在測presenter的时候自然就遇到了mock view的问题。

过于mock对象以前了解过一些,原以为倒也不难。找了下.net下常用的几种mock framework,看了些比较,rinho mock2好评比较多,就去code project下了个demo来看看。这一看倒是看出问题来了。

            MockRepository mocks = new MockRepository();
            IProjectView projectView 
= (IProjectView)mocks.CreateMock<IProjectView>();
            Project.Project prj 
= new Project.Project("Example Project");
            IProjectPresenter presenter 
= new ProjectPresenter(prj, projectView);
            Expect.Call(projectView.Title).Return(prj.Name);
            Expect.Call(projectView.Ask(question, answer)).Return(
null);
            mocks.ReplayAll();
            Assert.IsFalse(presenter.SaveProjectAs());
            mocks.VerifyAll();

前面几句,创建一个mock生成器,用Expect设置对象的返回值。这里我对Expect还不太理解,直觉这个命名不太容易理解,不过也可以接受。然后Assert一个结果。到此为之都没问题,可是最后一句mock.VerifyAll()是干吗的呢?

去查了下文档,VerifyAll是说如果我不按照预订的顺序调用mock对象中的方法,MockRepository会抛出异常——这一下我就炸锅了——感情我用Mock的话不但要关心mock对象的返回值,还要关心它的内部实现啊。

第一个反应这就是违反了OO中封装的原则。按照封装来说,一个Object暴露出来一个function就是承诺其能实现一定的功能,至于其内部实现,对不起,就不是调用者该关心的了。人家爱到月球转一圈也可以,只要能完成contract中规定的事就行了。您自己写个单元测试也就只需要测所有交互对象能按照contract保质保量提供服务的情况下被测试的function能否干好自己的活儿就行了,管那么宽干吗?

先以为是我理解上的问题,就去google了一把。这一看,原来虚拟对象还分好多种,我以前一直用的那种其实都是个stub,如果真正用mock的话就得是管的这么事无巨细。网上对mock的争论也挺多的,也有很多人说大多数情况其实用stub就够了,只有在牵涉到file,db,network时要用用mock。

话虽然这么说,我也没想明白为什么要在牵涉到这三种资源时用mock啊。在我看来,mock和stub(不论其实现)最大的区别就是mock要管人家实现,人家没按你所理解的实现你还不认,而stub不用像太平洋警察管那么宽。那我觉得是无论如何没法接受mock的。在我的理解中,对于一个function来说,它和外界的contract只应该包括input arguments, post-condition和return result。至于内部实现,是万万不应该暴露的。比如对于一个inc()来说,内部究竟是写成

i++;

 

还是

i=i+2;
emptyfunction1();
int j=i-1;
emptyfunction2();
i
=j;

 

都不是调用inc()的方法该关心的。如果其明确声明inc()不会调用emptyfunction1()和emptyfunction()2并在contract中要求调用者检查的话是一种推卸责任的行为。这样一来,一旦inc()改变了内部实现,所有调用inc()的对象都要去修改test case,这是何等紧密的耦合啊!

所以,至少到现在,我找不到用mock的理由。以后我要测试的话还是宁愿写个stub,最多是用用PartialMock之类不会要求校验内部实现的方法。至于那行mock.VerifyAll(),在我找到充分理由之前是绝不会用它的。

版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

PowerMock中replayAll,verifyAll,resetAll 方法的使用

Quick summary Use PowerMock.replayAll to change all mocks object and classes maintained by PowerMoc...

Python2.7 安装mock出现AttributeError: 'module' object has no attribute的解决方法

原环境: 1.pip --verson : 1.0 from /usr/lib/python2.7/dist-packages (python 2.7) 2.uname -a :Linux pc 3....

spring-mock.jar.zip

  • 2016-12-20 09:59
  • 96KB
  • 下载

android mock的文档

  • 2012-10-17 20:06
  • 356KB
  • 下载

Debug过程中的mock (及display窗口的使用)

在debug的时候,有3个地方可以进行mock测试 测试代码如下: 1.使用display窗口 Window-->Show View-->Other-->Display, 将display窗口...

Mock+Proxy在SDK项目的自动化测试实战

项目背景广告SDK项目是为应用程序APP开发人员提供移动广告平台接入的API程序集合,其形态就是一个植入宿主APP的jar包。提供的功能主要有以下几点: - 为APP请求广告内容 - 用户行为打点...
  • wpyily
  • wpyily
  • 2016-10-18 10:47
  • 3096

google mock doc

  • 2014-08-05 14:06
  • 122KB
  • 下载

SCJP Mock Exam one

  • 2008-04-14 13:31
  • 76KB
  • 下载
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)