Mock Object工具横向比较(上)

原创 2004年03月15日 09:25:00

前言

  本文:
  1、仅对动态Mock工具和能自动生成Mock Object实现的工具进行比较
  2、仅对文中所列的几种有限的工具进行比较
  3、仅进行使用方面的对比,不涉及技术方面的比较
  可以看作是一份使用Mock Object辅助单元测试的入门手册。

  在现在流行的各种软件开发的实践或理论中,单元测试(UT,Unit Test)都已经作为一个软件开发的“最佳实践”而被普遍接受。而JUnit则是单元测试工具中无可争议的王者。
  当我们对简单对象或算法进行测试时,撰写基于JUnit的单元测试很简单。当我们准备测试一个依赖于其他对象的类或算法时,就需要构造出这些合作者的实例。这时,测试用例的撰写就略显复杂了。更进一步,当我们准备对一个Web系统或复杂的业务进行单元测试的时候,构造“合作者”实例的工作可能就会是低效而昂贵的。
  例如:测试一个使用HttpRequest实例的对象,需要启动Web服务器,构造Request实例并填入所需要的值,测试完后需要停止Web服务器。这样,测试数据的构造和环境的准备可能会非常复杂,甚至会难以达到“自动测试”的目标。

Mock Object

  此时,Mock Object给我们提出一个解决方案:Mock Object拥有与被测对象的“合作者”完全一致的接口,在测试中作为“合作者”被传递给被测对象;当被测对象调用合作者时,Mock Object根据测试者的意愿改变某些状态或返回期望的结果,以检查被测程序是否按照所期望的逻辑进行工作,达到单元测试的目的。
图1
图2
  或者说,Mock Object作为“仿真器”出现在单元测试用例中,对被测对象进行“欺骗”和跟踪。而只要Mock Object的行为与被测对象所期望的一致,就不会对被测对象产生任何影响。
  当我们借助Mock Object撰写单元测试用例时,代码样式通常会是这样:
1.        创建:创建Mock Object的实例
2.        训练:设置Mock Object中的状态和期望值
3.        测试:将Mock Object作为参数来调用被测对象
4.        验证:验证Mock Object中的一致性和被测对象的返回值或状态
  第2步我们通常称之为Mock Object的训练。此时,我们需要“告诉”Mock Object被测对象会调用它的哪些接口、调用的顺序和次数是什么、它应该做出什么反应。第4步的时候,Mock Object就会按照前面训练的内容一一检查被测对象是否调用了那些指定的接口、调用的顺序和调用次数是否正确。如果正确的话就一切OK,否则说明被测对象没有实现所期望的功能。
  从上面的描述中,我们可以看出,Mock Objects
1.        可以仿真被模拟的对象、构建虚拟测试环境;
2.        能够设定有哪些接口将要被调用、并在那时执行期望的动作;
3.        可以验证被测对象是否按照设定的规则调用Mock Object。

Mock Object Generate Tool

  最开始,Mock Object是完全由测试者自己手工撰写的。这样,无可避免的会带来编写测试用例效率低下和测试用例编写困难的弊病,甚至可能会影响XP实践者“测试先行”的激情。此时,各种各样帮助创建Mock Object的工具就应运而生了。
  这些工具中,有MockObjects、XDoclet等帮助程序员编写Mock Object实现的工具,也有EasyMock、MockCreator等自动创建Mock Object实例/类的工具。本文仅针对后者进行描述。
  在这些能自动创建Mock Object实例/类的工具中,又分为两种:一种类似于EasyMock,他们能够动态创建Mock Object实例;一种就像MockCreator,他们可以生成静态的Mock Object代码。最有名且目前仍在维护的有如下几个工具:MockObjects、EasyMock、MockCreator。下面,我们将使用这几种工具分别为下面这个类编写单元测试代码,逐次比较他们使用上的异同:
 
 

package mocktest;
 
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
 
public class SimpleCalcServlet extends HttpServlet
{
    public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException
    {
        Integer a = Integer.decode(request.getParameter("a"));
        Integer b = Integer.decode(request.getParameter("b"));
 
        int result = a.intValue() + b.intValue();
        response.setContentType("text/html");
 
        PrintWriter out = response.getWriter();
        out.print("Result = " + result);
        out.flush();
    }
}
  这个类是一个Servlet,我们可以通过JUnit的一个扩展:HttpUnit来编写它的测试用例。不过,如何使用HttpUnit进行测试不是本文所讨论的内容。
  如果利用Mock Object来为这个类编写单元测试用例的话,问题的实质在于如何构造HttpServletRequest和HttpServletResponse的实例。下面,我们将一一展示如何使用上面提到的工具来解决这个问题:

MockObjects

  我们有四种方式来利用MockObjects编写测试用例:
1、基于MockObjects的框架编写自己的Mock Object实现并与其他人分享;
2、直接使用MockObjects提供的Mock Object进行测试;
3、使用其中包含的DynaMock模块快速获取Mock Object实例;
4、通过它提供的Helpers对象帮助我们快速构建测试环境。
  不过,本文仅关注如何使用DynaMock来编写测试用例[1]
 
 

1.   public void testSimpleAdditionUsingDynaMock() throws ServletException, IOException {
2.       final Mock mockHttpServletRequest = new Mock(HttpServletRequest.class);
3.       final Mock mockHttpServletResponse = new OrderedMock(HttpServletResponse.class,
4.               "Response with non-default name");
5.
6.      mockHttpServletRequest.expectAndReturn("getParameter", "b", "4");
7.       mockHttpServletRequest.expectAndReturn("getParameter", "a", "3");
8.
9.       final StringWriter output = new StringWriter();
10.      final PrintWriter contentWriter = new PrintWriter(output);
11.
12.      mockHttpServletResponse.expect("setContentType", "text/html");
13.      mockHttpServletResponse.expectAndReturn("getWriter", contentWriter);
14.
15.      SimpleCalcServlet aServlet = new SimpleCalcServlet();
16.      aServlet.doGet((HttpServletRequest) mockHttpServletRequest.proxy(), 
17.                     (HttpServletResponse) mockHttpServletResponse.proxy());
18.
19.      mockHttpServletRequest.verify();
20.      mockHttpServletResponse.verify();
21.      assertEquals("Output should be an addition", "Result = 7", output.toString());
22.  }
  对照“Mock Object”一节所言的“代码样式”,Line2~4即为“创建”Mock Object实例:
●我们使用了两个不同的类来构造Mock Object:一个是Mock,一个是OrderedMock。他俩的异同在于一个不检测接口被调用的次序,一个需要检测接口被调用的次序。
  Line6~13为“训练”Mock Object:
●在训练Mock Object的时候,我们调用了它的expectAndReturn()方法。此方法有多个重载。对于测试方法第6行来说,它表达了这样一个意思:被测代码将传入参数“b”来调用mockHttpServletRequest的getParameter()方法;当接收到此消息时,mockHttpServletRequest将返回字符串“4”。
  Line15~17为“测试”:
●实际进行测试的时候,通过调用Mock类实例的proxy()方法将Mock Object实例传递给被测代码。
  Line19~21为“验证”:
●此时,使用Mock类实例的verify()方法进行一致性验证。


[1] 为了节省篇幅、简单起见,本文只列出JUnit测试用例中test方法的代码。

Mock Object工具横向比较(上)

  • zgqtxwd
  • zgqtxwd
  • 2008年04月25日 09:02
  • 265

Mock Object工具横向比较(下)

  • zgqtxwd
  • zgqtxwd
  • 2008年04月25日 09:02
  • 207

Java 各种Mock工具比较

转自: http://billben.iteye.com/blog/1872196 http://harrywu304.blog.163.com/blog/static/84566032011...
  • yasi_xi
  • yasi_xi
  • 2014年04月28日 14:56
  • 16291

junit--用mock object进行隔离测试(上)

最近抽空翻译了一下manning出版的junit in action,译的比候捷还糟,大家不要bt.以下是第7章的内容第一节   mock object 的介绍:      隔离测试有很多好处,比如测...
  • huabingl
  • huabingl
  • 2005年02月28日 21:18
  • 4437

一个mp4文件分析工具

http://blog.chinaunix.net/space.php?uid=11857489&do=blog&id=2814505
  • eustoma
  • eustoma
  • 2011年12月22日 15:39
  • 1982

使用mock object做单元测试,mock object如何插入?

我所关心的是mock object的插入方式问题。因为所见过的例子当中,都是把被mock的interface实现类实例作为被测试类的instance field的。然后,mock object替代re...
  • arwong
  • arwong
  • 2006年06月01日 15:14
  • 782

说说初用 Mock 工具测试碰到的坑

说说初用 Mock 工具测试碰到的坑 我是一个在校实习生,作为一个程序猿,是个菜鸟中战斗机!对于测试,只写过一点点简单到不能再简单了的 Junit 单元测试的例子(因为当时这足以应付学校课程的内容...
  • GarfieldEr007
  • GarfieldEr007
  • 2016年12月27日 22:57
  • 2090

接口自动化测试:mock server之Moco工具

什么是mock server mock:英文可以翻译为模仿的,mock server是我们用来解除依赖(耦合),假装实现的技术,比如说,前端需要使用某些api进行调试,但是服务端并没有开发完成这些...
  • qq_14908027
  • qq_14908027
  • 2017年09月03日 12:01
  • 581

Mock,前端mock数据的神器

相信有很多小伙伴在开发的时候遇到过这样的问题:静态页面写好了,就等后端给数据了!WTF?我刚写好代码你告诉我后端的接口又变了!什么破网啊根本访问不到服务器啊…这个时候就需要前端神器Mock.js了(妈...
  • StayHungry_
  • StayHungry_
  • 2016年08月10日 18:20
  • 7781

使用Mock Object测试界面

       在编写Swing界面的时候,发现运用Mock Object可以很容易的实现界面的测试。在编写程序的时候,很多依赖外部的地方都要留个后门,不能硬写在程序里面,有的是做成setter,get...
  • moneyice
  • moneyice
  • 2006年05月28日 23:27
  • 1528
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Mock Object工具横向比较(上)
举报原因:
原因补充:

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