from:http://macrochen.iteye.com/blog/298032

关于EasyMock常见的几个问题, 这里(http://ozgwei.blogspot.com/2007/06/easymock2-quirk.html)有几点, 我做个翻译: 
★EasyMock在录制的时候最典型的写法:

  1. expect(mockEmployeeRepository.findByFirstNameAndLastName("John", "Doe")).andReturn(employees);

★如果有个要录制的方法只知道类型不知道具体的值, 可以这样写:

  1. expect(mockEmployeeRepository.findBySpecification(isA(EmployeeSearchSpecification.class))
  2. .andReturn(employees);

★出现这样的异常: 
java.lang.IllegalStateException: 2 matchers expected, 1 recorded. 
可能是设置mock方法的期望调用方式时, 既使用了isA的方式来指定参数, 又使用了一个具体值来作为参数 
比如这样写:

  1. expect(mockEmployeeRepository.findByDepartmentAndSpecification("HR",
  2. isA(EmployeeSearchSpecification.class)).andReturn(emplooyees);

正确的写法:

  1. expect(mockEmployeeRepository.findByDepartmentAndSpecification(eq("HR"),
  2. isA(EmployeeSearchSpecification.class)).andReturn(employees);

★andReturn()只是用于当mock对象的方法需要有返回值的情况下,手动设置这个方法的返回值给调用的测试类的。在本例中methodABC (arguments,……)方法就需要在recorder的时候用andReturn()方法指定返回值给TargetClass。如果对于有返回值的方法不指定其返回值,在测试的时候会抛出”java.lang.IllegalStateException: missing behavior definition for the preceeding method call XXX”异常。

★一般不能这样写:

  1. EasyMock.expect(itemPropertyManager.processPublishOrEditSpu(EasyMock.isA(SpuDO.class),
  2. EasyMock.isA(BaseResultDO.class))).andReturn(EasyMock.isA(BaseResultDO.class));

而应该这样写:

  1. EasyMock.expect(itemPropertyManager.processPublishOrEditSpu(EasyMock.isA(SpuDO.class),
  2. EasyMock.isA(BaseResultDO.class))).andReturn(null));

否则会抛出这样的异常:

引用
java.lang.IllegalStateException: matcher calls were not used outside expectations 
at org.easymock.internal.RecordState.replay(RecordState.java:72) 
at org.easymock.internal.MocksControl.replay(MocksControl.java:57) 
at org.easymock.EasyMock.replay(EasyMock.java:1280) 

也就是说, 返回值必须给一个具体的值, 而不能只指定返回值类型

★在实用expect来设置mock方法的期望调用方式时, 如果使用到基本类型, 但是又不要基本类型的值, 一般不要这样写:

  1. EasyMock.expect(
  2. keywordsChecker.checkNormalKeywords(EasyMock
  3. .isA(String.class), EasyMock.isA(Long.class),
  4. EasyMock.isA(String.class))).andReturn("");

而应该这样写:

  1. EasyMock.expect(keywordsChecker.checkNormalKeywords(EasyMock.isA(String.class), EasyMock.anyLong(),
  2. EasyMock.isA(String.class))).andReturn("");

★EasyMock还有一个很让人郁闷的地方, 比如一个方法的参数可能为null, 而你在测试的时候又恰恰传了一个空值, 则这个测试是没法通过的, 会出现类似下面的异常:

引用
java.lang.AssertionError: 
  Unexpected method call checkFixKeywords(null, 50010815): 
    checkFixKeywords(isA(java.lang.String), <any>): expected: 1, actual: 0 
    checkNormalKeywords(isA(java.lang.String), <any>, isA(java.lang.String)): expected: 1, actual: 0 
at org.easymock.internal.MockInvocationHandler.invoke(MockInvocationHandler.java:29) 
at org.easymock.internal.ObjectMethodsFilter.invoke(ObjectMethodsFilter.java:45)

这也就要求被测试的方法, 参数不能传递空值. 
经过跟踪这个应该是EasyMock的一个bug:

  1. public class InstanceOf implements IArgumentMatcher {
  2. private final Class<?> clazz;
  3. public InstanceOf(Class clazz) {
  4. this.clazz = clazz;
  5. }
  6. public boolean matches(Object actual) {
  7. // 问题在这里:
  8. return (actual != null) && clazz.isAssignableFrom(actual.getClass());
  9. // 应该这样写:
  10. return (actual == null) || clazz.isAssignableFrom(actual.getClass());
  11. }
  12. public void appendTo(StringBuffer buffer) {
  13. buffer.append("isA(" + clazz.getName() + ")");
  14. }
  15. }

不过这个问题也不是不能绕过, 我用了下面的做法:

  1. EasyMock.expect(
  2. keywordsChecker.checkFixKeywords(
  3. (String) EasyMock.isNull(), EasyMock.anyLong()))
  4. .andReturn("");
  5. EasyMock.expect(
  6. keywordsChecker.checkFixKeywords(
  7. EasyMock.isA(String.class), EasyMock.anyLong()))
  8. .andReturn("").anyTimes();

后来我问了一下EasyMock开发者Tammo Freese, 看来不是能算一个bug, 他做了如下的回答:

引用
this is expected behavior, and it is also documented. 
The isA() matcher does the same thing as instanceof , so for null, it returns false.

If you would like to match any Object, use 
   anyObject() 
If you would like to match either Strings or null, use 
   or(isA(String.class), isNull())

这里录制了两个expect:将null和非空值分开, 但是第二个的返回值注意加上anyTimes(), 因为我的第二种情况会调用多次, 如果两种情况都会调用多次, 则都加上该方法即可, 否则会出现类似下面的异常:

引用
java.lang.AssertionError: 
  Unexpected method call checkFixKeywords("new test", 50010815): 
    checkFixKeywords(isA(java.lang.String), <any>): expected: 1, actual: 1 (+1) 
    checkNormalKeywords(isA(java.lang.String), <any>, isA(java.lang.String)): expected: 1, actual: 0 
at org.easymock.internal.MockInvocationHandler.invoke(MockInvocationHandler.java:32) 
at org.easymock.internal.ObjectMethodsFilter.invoke(ObjectMethodsFilter.java:61)

★静态方法是没法用EasyMock进行mock的

★如果需要expect的方法没有返回值, 应该这样写: 
先执行mock的要调用的方法, 然后调用EasyMock.expectLastCall().anyTimes();

★如果是对具体类进行mock, 则需要使用org.easymock.classextension.EasyMock去替换org.easymock.EasyMock, 当然这个需要加入对easymockclassextension的引用, 具体使用上则没有区别, 如果采用maven构建工程, 则可以采用下面的写法:

  1. <!-- mock 相关 -->
  2. <dependency>
  3. <groupId>org.easymock</groupId>
  4. <artifactId>easymock</artifactId>
  5. <version>2.4</version>
  6. </dependency>
  7. <dependency>
  8. <groupId>org.easymock</groupId>
  9. <artifactId>easymockclassextension</artifactId>
  10. <version>2.2.1</version>
  11. </dependency>
  12. <!-- mock 相关 end-->

★通常对一个方法进行测试的时候, mock一个对象的情况比较多见, 于是我写了下面的一个比较通用的抽象类:

  1. public abstract class AbstractMockExecutor<T> {
  2. protected T mock;
  3. /**
  4. * @param clazz
  5. * @return
  6. */
  7. protected T createMock(Class<T> clazz) {
  8. mock = EasyMock.createMock(clazz);
  9. return mock;
  10. }
  11. public void execute() throws Exception {
  12. record();
  13. EasyMock.replay(mock);
  14. invoke();
  15. verify();
  16. }
  17. /**
  18. * 创建mock对象, 并对要mock的方法进行方法录制, 必须在该方法中手动调用{@link #createMock(Class)}方法.<br>
  19. * 该方法的一般做法如下:
  20. *
  21. * <pre>
  22. * createMock(MockClass);
  23. * EasyMock.expect(mock.mockMethod(mockArgument...)).andReturn(
  24. *      mockResult);
  25. * BeanObject.setter(mock);
  26. * </pre>
  27. *
  28. * @throws Exception
  29. */
  30. protected abstract void record() throws Exception;
  31. /**
  32. * 调用经过mock之后的执行过程
  33. */
  34. protected abstract void invoke() throws Exception;
  35. /**
  36. * 验证mock是否正确
  37. */
  38. public void verify() {
  39. EasyMock.verify(mock);
  40. }
  41. }

2012-01 更新: 
有时候我们会碰到这样的异常信息: 
matcher calls were used outside expectations 
后来在网上google了一把, 这里有个说明. 
简单的说就是andReturn(xxx)中的xxx不能使用EasyMock.anyObject()这样的方法来指定结果. 但是它没有说解决办法. 这里可以利用andAnswer(), 比如这样写:

    1. final AtomicLong count = new AtomicLong(10000L);
    2. EasyMock.expect(db.count()).andAnswer(new IAnswer<Long>() {
    3. @Override
    4. public Long answer() throws Throwable {
    5. return count.getAndIncrement();
    6. }
    7. }).times(10);

easymock入门贴的更多相关文章

  1. EasyMock入门

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

  2. easymock快速入门

    easymock是众多mock之中的很容易用的mock,今天刚开始学习,来个简单的教程.以购物车结算为例子,比如首先是每一个商品项的pojo. public class Item { private ...

  3. easymock+junit+spring学习·

    Easymock学习                                Author:luojie 1.       Easymock简介 EasyMock 是一套通过简单的方法对于指定的 ...

  4. 前端入门20-JavaScript进阶之异步回调的执行时机

    声明 本系列文章内容全部梳理自以下几个来源: <JavaScript权威指南> MDN web docs Github:smyhvae/web Github:goddyZhao/Trans ...

  5. 前端入门6-JavaScript客户端api&jQuery

    本篇文章已授权微信公众号 dasu_Android(大苏)独家发布 声明 本系列文章内容全部梳理自以下四个来源: <HTML5权威指南> <JavaScript权威指南> MD ...

  6. PowerMock学习(一)之PoweMock的入门--模拟新增学生操作

    关于powermock 在TDD领域Mock框架有很多,比如EasyMock,JMock,Mockito.可能有些同学会好奇了,为什么要重点把powermock拿出来呢,因为powermock可以解决 ...

  7. PowerMock学习之PoweMock的入门(二)

    前言 在上一篇<PowerMock学习之PoweMock的入门(一)>文章中,已经简单提及一些关于powermock的用法,但是入门还未完,我还要坚持把它学习并坚持更新到博客中. Mock ...

  8. Mockito -- 入门篇

    Mockito是一种mock工具/框架.我理解EasyMock有点过时了,Mockito是现在比较流行的. 什么是mock?说的直白一点,大家都知道unit test应该是尽可能独立的.对一个clas ...

  9. Angular2入门系列教程7-HTTP(一)-使用Angular2自带的http进行网络请求

    上一篇:Angular2入门系列教程6-路由(二)-使用多层级路由并在在路由中传递复杂参数 感觉这篇不是很好写,因为涉及到网络请求,如果采用真实的网络请求,这个例子大家拿到手估计还要自己写一个web ...

随机推荐

  1. Android Volley源码分析

    今天来顺手分析一下谷歌的volley http通信框架.首先从github上 下载volley的源码, 然后新建你自己的工程以后 选择import module 然后选择volley. 最后还需要更改 ...

  2. JBPM4入门——6.流程实例的创建和执行

    本博文只是简要对JBPM4进行介绍,如需更详细内容请自行google 链接: JBPM入门系列文章: JBPM4入门——1.jbpm简要介绍 JBPM4入门——2.在eclipse中安装绘制jbpm流 ...

  3. library cache lock和cursor: pin S wait on X等待

    1.现象: 客户10.2.0.4 RAC环境,出现大量的library cache lock和cursor: pin S wait on X等待,经分析是由于统计信息收集僵死导致的.数据库在8点到9点 ...

  4. 顺序表的基本操作(C)

    在顺序存储结构实现基本操作:初始化.创建.插入.删除.查找.遍历.逆置.合并运算. 运行示例: 请输入线性表La的长度: 请输入线性表La中的元素(共5个) *** 此时线性表La中的元素 *** * ...

  5. [python]Python操作MySQL

    [安装] 安装MySQL 安装MySQL不用多说了,下载下来安装就是,没有特别需要注意的地方. 一个下载地址:点击打开链接 [样例] ? 1 2 3 4 5 6 7 8 9 10 11 12 13 1 ...

  6. Windows 下命令行修改文件夹的控制权限 Cacls

    设置用户访问权限:我们经常要修改目录和文件的访问权限,使用Cacls命令就很容易做到.下面要赋予本机用户testuser对d盘下 test目录及其所有子目录中的文件有完全控制权限.在命令提示符对话框中 ...

  7. how to install flash

    Choice 1: Install  Flash from Repository: This is fairly simple and easy and should work from most p ...

  8. Yarn中的几种状态机

    1 概述 为了增大并发性,Yarn采用事件驱动的并发模型,将各种处理逻辑抽象成事件和调度器,将事件的处理过程用状态机表示.什么是状态机? 如果一个对象,其构成为若干个状态,以及触发这些状态发生相互转移 ...

  9. 桶排序-Node.js-对象排序

    const b = [{index:5,name:"s5"}, {index:2,name:"s2"}, {index:3,name:"s3" ...

  10. 《Java数据结构与算法》笔记-CH4-6栈结构实现中缀转后缀

    /** * 中缀表达式转换成后缀表达式: 从输入(中缀表达式)中读取的字符,规则: 操作数: 写至输出 左括号: 推其入栈 右括号: 栈非空时重复以下步骤--> * 若项不为(,则写至输出: 若 ...