EasyMock最佳实践

转载 2012年03月27日 14:40:53

转载于:http://blog.sina.com.cn/s/blog_4b81125f0100hr57.html

关于EasyMock常见的几个问题, 这里有几点, 我做个翻译:
★EasyMock在录制的时候最典型的写法:
expect(mockEmployeeRepository .findByFirstNameAndLastName("John", "Doe")) .andReturn(employees);
★如果有个要录制的方法只知道类型不知道具体的值, 可以这样写:
expect(mockEmployeeRepository .findBySpecification(isA(EmployeeSearchSpecification.class)) .andReturn(employees);

★出现这样的异常:
java.lang.IllegalStateException: 2 matchers expected, 1 recorded.
可能是设置mock方法的期望调用方式时, 既使用了isA的方式来指定参数, 又使用了一个具体值来作为参数
比如这样写:
expect(mockEmployeeRepository .findByDepartmentAndSpecification("HR", isA(EmployeeSearchSpecification.class)) .andReturn(emplooyees);
正确的写法:
expect(mockEmployeeRepository .findByDepartmentAndSpecification(eq("HR"), isA(EmployeeSearchSpecification.class)) .andReturn(employees);

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

★一般不能这样写:
EasyMock.expect(itemPropertyManager.processPublishOrEditSpu(EasyMock.isA(SpuDO.class),
EasyMock.isA(BaseResultDO.class))).andReturn(EasyMock.isA(BaseResultDO.class));

而应该这样写:
EasyMock.expect(itemPropertyManager.processPublishOrEditSpu(EasyMock.isA(SpuDO.class),
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方法的期望调用方式时, 如果使用到基本类型, 但是又不要基本类型的值, 一般不要这样写:
EasyMock.expect(
keywordsChecker.checkNormalKeywords(EasyMock
.isA(String.class), EasyMock.isA(Long.class),
EasyMock.isA(String.class))).andReturn("");

而应该这样写:
EasyMock.expect(
keywordsChecker.checkNormalKeywords(EasyMock
.isA(String.class), EasyMock.anyLong(),
EasyMock.isA(String.class))).andReturn("");

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

java.lang.AssertionError:
Unexpected method call checkFixKeywords(null, 50010815):
checkFixKeywords(isA(java.lang.String), ): expected: 1, actual: 0
checkNormalKeywords(isA(java.lang.String), , 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:
public class InstanceOf implements IArgumentMatcher {

private final Class< ?> clazz;

public InstanceOf(Class clazz) {
this.clazz = clazz;
}

public boolean matches(Object actual) {
// 问题在这里:
return (actual != null) && clazz.isAssignableFrom(actual. getClass_r());
// 应该这样写:
return (actual == null) || clazz.isAssignableFrom(actual. getClass_r());
}

public void appendTo(StringBuffer buffer) {
buffer.append("isA(" + clazz. getName_r() + ")");
}
}

不过这个问题也不是不能绕过, 我用了下面的做法:
EasyMock.expect(
keywordsChecker.checkFixKeywords(
(String) EasyMock.isNull(), EasyMock.anyLong()))
.andReturn("");
EasyMock.expect(
keywordsChecker.checkFixKeywords(
EasyMock.isA(String.class), EasyMock.anyLong()))
.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), ): expected: 1, actual: 1 (+1)
checkNormalKeywords(isA(java.lang.String), , 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的

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


protected T createMock(Class clazz) {
mock = EasyMock.createMock(clazz);
return mock;
}

public void execute() throws Exception {
replay();
EasyMock.replay(mock);
invoke();
verify();
}


protected abstract void replay() throws Exception;


protected abstract void invoke() throws Exception;


public void verify() {
EasyMock.verify(mock);
}
}

 

EasyMock使用简明手册

在实际编写unit test的过程中,很多情况下我们会需要使用其他的组件(如和数据库相关的测试)。当我们是使用第三方提供的组件时,这并不是太大的问题,因为我们可以假设他们是无错的。但是一旦这些组件是...
  • Coolingverse
  • Coolingverse
  • 2005年10月17日 11:16
  • 776

Maven环境下easymock开发入门实例

在大项目中,都是分模块来完成,比如dao层的数据操作接口没有完成,那么调用它的service层也就无法进行开发和测试了,mock框架就是来解决这个问题的,它只关注业务交互层的操作。 (mock关注的...
  • tianjun2012
  • tianjun2012
  • 2016年01月23日 23:09
  • 658

【JUnit】EasyMock用法总结

使用EasyMock的总体步骤 1、生成Mock接口 IService mockService = EasyMock.createMock("name", IService.class); 如...
  • vking_wang
  • vking_wang
  • 2013年06月25日 16:52
  • 14495

使用PowerMock和Easymock进行单元测试

Java单元测试对于开发人员质量保证至关重要,尤其当面对一团乱码的遗留代码时,没有高覆盖率的单元测试做保障,没人敢轻易对代码进行重构。然而单元测试的编写也不是一件容易的事情,除非使用TDD方式,否则编...
  • u010860412
  • u010860412
  • 2016年02月16日 20:11
  • 1332

easyMock 使用总结

转 http://www.cnblogs.com/sequence/archive/2011/07/28/2119657.html easyMock 使用总结 一、 准备 1. 引包...
  • zhoujianli12
  • zhoujianli12
  • 2012年04月17日 23:06
  • 792

用EasyMock进行单元测试:什么是EasyMoc

原文:http://www.zhlwish.com/2012/06/29/easymock-1/ 用EasyMock进行单元测试:什么是EasyMock 发: 周亮 我们都知道单元测试,也...
  • xiongmc
  • xiongmc
  • 2013年07月02日 19:31
  • 1284

聊聊单元测试(一)——EasyMock

一、单元测试是保证软件质量的重要方法。 单元测试是对系统中某个模块功能的验证,但我们总会遇到这样那样的问题,导致测试代码很难编写。最直接的一个原因便是强耦合关系,被测试者依赖一些不容易构造,...
  • shan9liang
  • shan9liang
  • 2014年07月11日 10:00
  • 4059

EasyMock问题总结

最近开发中同事遇到过很多EasyMock的问题,也许有时候会怀疑easyMock是不是出了问题,其实99.99%的情况都是我们自己的代码出了问题,所以请认真的检查出错前后代码。...
  • andywangcn
  • andywangcn
  • 2014年03月11日 18:43
  • 1998

easyMock测试action

环境搭建: EasyMock is available in theMaven central repository. Just add the following dependency to yo...
  • woshiyjk
  • woshiyjk
  • 2012年08月22日 14:39
  • 1664

使用EasyMock对Servlet进行简单的测试

完整版见https://jadyer.github.io/2013/07/09/easymock-servlet/
  • jadyer
  • jadyer
  • 2013年07月09日 14:30
  • 2527
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:EasyMock最佳实践
举报原因:
原因补充:

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