Mock Objects in Unit Tests

转载 2005年02月25日 22:43:00
Mock Objects in Unit Tests by Lu Jian
01/12/2005

The use of mock objects is a widely employed unit testing strategy. It shields external and unnecessary factors from testing and helps developers focus on a specific function to be tested.

Advertisement
EasyMock is a well-known mock tool that can create a mock object for a given interface at runtime. The mock object's behavior can be defined prior encountering the test code in the test case. EasyMock is based on java.lang.reflect.Proxy, which can create dynamic proxy classes/objects according to given interfaces. But it has an inherent limitation from its use of Proxy: it can create mock objects only for interfaces.

Mocquer is a similar mock tool, but one that extends the functionality of EasyMock to support mock object creation for classes as well as interfaces.

Introduction to Mocquer

Mocquer is based on the Dunamis project, which is used to generate dynamic delegation classes/objects for specific interfaces/classes. For convenience, it follows the class and method naming conventions of EasyMock, but uses a different approach internally.

MockControl is the main class in the Mocquer project. It is used to control the the mock object life cycle and behavior definition. There are four kinds methods in this class.

  • Life Cycle Control Methods
    
    

    The mock object has three states in its life cycle: preparing, working, and checking. Figure 1 shows the mock object life cycle.

    Mock Object Life Cycle
    Figure 1. Mock object life cycle

    Initially, the mock object is in the preparing state. The mock object's behavior can be defined in this state. replay() changes the mock object's state to the working state. All method invocations on the mock object in this state will follow the behavior defined in the preparing state. After verify() is called, the mock object is in the checking state. MockControl will compare the mock object's predefined behavior and actual behavior to see whether they match. The match rule depends on which kind of MockControl is used; this will be explained in a moment. The developer can use replay() to reuse the predefined behavior if needed. Call reset(), in any state, to clear the history state and change to the initial preparing state.

  • Factory Methods
    
    

    Mocquer provides three kinds of MockControls: Nice, Normal, and Strict. The developer can choose an appropriate MockControl in his or her test case, according to what is to be tested (the test point) and how the test will be carried out (the test strategy). The Nice MockControl is the loosest. It does not care about the order of method invocation on the mock object, or about unexpected method invocations, which just return a default value (that depends on the method's return value). The Normal MockControl is stricter than the Nice MockControl, as an unexpected method invocation on the mock object will lead to an AssertionFailedError. The Strict MockControl is, naturally, the strictest. If the order of method invocation on the mock object in the working state is different than that in the preparing state, an AssertionFailedError will be thrown. The table below shows the differences between these three kinds of MockControl.

      Nice Normal Strict
    Unexpected Order Doesn't care Doesn't care AssertionFailedError
    Unexpected Method Default value AssertionFailedError AssertionFailedError

    There are two versions for each factory method.

    
    

    If the class to be mocked is an interface or it has a public/protected default constructor, the first version is enough. Otherwise, the second version factory method is used to specify the signature and provide arguments to the desired constructor. For example, assuming ClassWithNoDefaultConstructor is a class without a default constructor:

    
    

    The MockControl can be obtained through:

    
    
  • Mock object getter method
    
    

    Each MockControl contains a reference to the generated mock object. The developer can use this method to get the mock object and cast it to the real type.

    
    
  • Behavior definition methods
    
    

    MockControl allows the developer to define the mock object's behavior per each method invocation on it. When in the preparing state, the developer can call one of the mock object's methods first to specify which method invocation's behavior is to be defined. Then, the developer can use one of the behavior definition methods to specify the behavior. For example, take the following Foo class:

    
    
    The behavior of the mock object can be defined as in the following:
    
    

    Most of the more than 50 methods in MockControl are behavior definition methods. They can be grouped into following categories.

    • setReturnValue()

      These methods are used to specify that the last method invocation should return a value as the parameter. There are seven versions of setReturnValue(), each of which takes a primitive type as its parameter, such as setReturnValue(int i) or setReturnValue(float f). setReturnValue(Object obj) is used for a method that takes an object instead of a primitive. If the given value does not match the method's return type, an AssertionFailedError will be thrown.

      It is also possible to add the number of expected invocations into the behavior definition. This is called the invocation times limitation.

      
      

      The code segment above specifies that the method invocation, bar(10), can only occur once. How about providing a range?

      
      

      Now bar(10) is limited to be called at least once and at most, three times. More appealingly, a Range can be given to specify the limitation.

      
      

      Range.ONE_OR_MORE is a pre-defined Range instance, which means the method should be called at least once. If there is no invocation-count limitation specified in setReturnValue(), such as setReturnValue("Hello"), it will use Range.ONE_OR_MORE as its default invocation-count limitation. There are another two predefined Range instances: Range.ONE (exactly once) and Range.ZERO_OR_MORE (there's no limit on how many times you can call it).

      There is also a special set return value method: setDefaultReturnValue(). It defines the return value of the method invocation despite the method parameter values. The invocation times limitation is Range.ONE_OR_MORE. This is known as the method parameter values insensitive feature.

      
      
    • setThrowable

      setThrowable(Throwable throwable) is used to define the method invocation's exception throwing behavior. If the given throwable does not match the exception declaration of the method, an AssertionFailedError will be thrown. The invocation times limitation and method parameter values insensitive features can also be applied.

      
      
    • setVoidCallable()

      setVoidCallable() is used for a method that has a void return type. The invocation times limitation and method parameter values insensitive features can also be applied.

      
      
    • Set ArgumentsMatcher

      In the working state, the MockControl will search the predefined behavior when any method invocation has happened on the mock object. There are three factors in the search criteria: method signature, parameter value, and invocation times limitation. The first and third factors are fixed. The second factor can be skipped by the parameter values insensitive feature described above. More flexibly, it is also possible to customize the parameter value match rule. setMatcher() can be used in the preparing state with a customized ArgumentsMatcher.

      
      

      The only method in ArgumentsMatcher, matches(), takes two arguments. One is the expected parameter values array (null, if the parameter values insensitive feature applied). The other is the actual parameter values array. A true return value means that the parameter values match.

      
      

      There are three predefined ArgumentsMatcher instances in MockControl. MockControl.ALWAYS_MATCHER always returns true when matching, no matter what parameter values are given. MockControl.EQUALS_MATCHER calls equals() on each element in the parameter value array. MockControl.ARRAY_MATCHER is almost the same as MockControl.EQUALS_MATCHER, except that it calls Arrays.equals() instead of equals() when the element in the parameter value array is an array type. Of course, the developer can implement his or her own ArgumentsMatcher.

      A side effect of a customized ArgumentsMatcher is that it defines the method invocation's out parameter value.

      
      
      setDefaultMatcher() sets the MockControl's default ArgumentsMatcher instance. If no specific ArgumentsMatcher is given, the default ArgumentsMatcher will be used. This method should be called before any method invocation behavior definition. Otherwise, an AssertionFailedError will be thrown.
      
      
      If setDefaultMatcher() is not used, MockControl.ARRAY_MATCHER is the system default ArgumentsMatcher.

MySQL 源码编译安装报错 Googlemock was not found

今天编译安装mysql 5.6.27的时候报错。 执行命令: shell> cmake . \ > -DCMAKE_INSTALL_PREFIX=/usr/local/mysql \ > -DMY...
  • gua___gua
  • gua___gua
  • 2015年11月10日 20:03
  • 1971

Mock Objects in Unit Testing

在MSN上遇到了老哥(chen56)得知最近辞职在家开发了一个小工具,并放到了sf.net上HiMock   http://himock.sourceforge.net/以前对TDD了解一些,实践过几...
  • errorter
  • errorter
  • 2004年08月11日 00:00
  • 836

如何在Java Unit Test中mock 静态方法

在我们平时写单元测试的时候有时候需要mock掉类里面的部分或者全部静态方法,这个需要用到那一些jar呢?以及需要怎么样的配置呢。下面是一些关于这些方面的分享:    1. 假如我们有下面的一个类:Pu...
  • west_609
  • west_609
  • 2017年07月09日 22:01
  • 388

Mock的基本概念和方法(续)

本博客(http://blog.csdn.net/livelylittlefish )贴出作者(三二一@小鱼)相关研究、学习内容所做的笔记,欢迎广大朋友指正! Content 0. 序 ...
  • livelylittlefish
  • livelylittlefish
  • 2011年04月25日 13:50
  • 9672

CentOS6.4 install mysql5.6.14 errors

install cmake need gcc support yum install gcc yum install gcc-c++ 安装cmake 完成之后, 使用时遇到一个问题:...
  • yhcelebrite
  • yhcelebrite
  • 2013年10月16日 14:03
  • 1912

android unit test

Android UI自动化测试最佳实 http://qa.baidu.com/blog/?p=985
  • songsallyjin
  • songsallyjin
  • 2015年08月07日 15:51
  • 821

用 Swift、Foursquare API 和 Realm 創建一個咖啡店 App

人們常說,程序員能將咖啡變成電腦程式。接下來,我們將編寫一個 App,列出距離你最近的咖啡屋!在本教程中,你將使用到如下技能: Swift、Xcode 和 Interface Builder ...
  • kmyhy
  • kmyhy
  • 2016年04月08日 17:52
  • 1968

iOS开发之单元测试/Unit Tests

iOS单元测试/Unit Tests
  • feng2qing
  • feng2qing
  • 2016年06月24日 13:50
  • 2685

Vue单元测试起步

最近在搭建一个项目的前端开发环境,准备趁此把一些没用过的东西尝试下,比如:单元测试。 使用 vue-cli 可以直接生成一个包含 unit 、 e2e 测试的开发环境,不过还是需要去了解其中的组...
  • hsany330
  • hsany330
  • 2017年06月23日 14:09
  • 2394

Unit tests

Unit tests are automated tests that verify functionality at the component, class, method, or propert...
  • liuchunming033
  • liuchunming033
  • 2014年03月26日 18:08
  • 604
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Mock Objects in Unit Tests
举报原因:
原因补充:

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