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(),在我找到充分理由之前是绝不会用它的。

Mockito单元测试——verify

1,校验方法是否调用 Mockito提供verify关键字来实现校验方法是否被调用,具体调用如下例子: @Test     public void testVerify() {    ...

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....

android mock的文档

  • 2012年10月17日 20:06
  • 356KB
  • 下载

google mock doc

  • 2014年08月05日 14:06
  • 122KB
  • 下载

如何让测试少加班?阿里Mock平台使用方法揭秘!

导读:作为一名测试,我们知道不是任何情况都可以用真实对象来测,比如我们要测一个地方PM2.5超过900的情况,我们不能每天等着PM2.5的指数超过900再测试,这个时候可以用一个虚拟对象来创建测试,做...

SCJP Mock Exam one

  • 2008年04月14日 13:31
  • 76KB
  • 下载

spring-mock-2.0.8.jar

  • 2010年01月09日 20:01
  • 102KB
  • 下载

用google mock模拟C++对象

google mock是用来配合google test对C++项目做单元测试的。它依赖于googletest(参见我上篇文章《如何用googletest写单元测试》: http://blog.csdn...

Mock Server(WebDoc)

  • 2017年08月16日 22:28
  • 14.77MB
  • 下载

mock学习交流

  • 2015年04月20日 19:26
  • 15KB
  • 下载
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:mock.VerifyAll()? NO!
举报原因:
原因补充:

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