easymock入门贴
from:http://macrochen.iteye.com/blog/298032
关于EasyMock常见的几个问题, 这里(http://ozgwei.blogspot.com/2007/06/easymock2-quirk.html)有几点, 我做个翻译:
★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));
否则会抛出这样的异常:
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, 而你在测试的时候又恰恰传了一个空值, 则这个测试是没法通过的, 会出现类似下面的异常:
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:
- 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());
- // 应该这样写:
- return (actual == null) || clazz.isAssignableFrom(actual.getClass());
- }
- public void appendTo(StringBuffer buffer) {
- buffer.append("isA(" + clazz.getName() + ")");
- }
- }
不过这个问题也不是不能绕过, 我用了下面的做法:
- 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, 他做了如下的回答:
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(), 因为我的第二种情况会调用多次, 如果两种情况都会调用多次, 则都加上该方法即可, 否则会出现类似下面的异常:
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构建工程, 则可以采用下面的写法:
- <!-- mock 相关 -->
- <dependency>
- <groupId>org.easymock</groupId>
- <artifactId>easymock</artifactId>
- <version>2.4</version>
- </dependency>
- <dependency>
- <groupId>org.easymock</groupId>
- <artifactId>easymockclassextension</artifactId>
- <version>2.2.1</version>
- </dependency>
- <!-- mock 相关 end-->
★通常对一个方法进行测试的时候, mock一个对象的情况比较多见, 于是我写了下面的一个比较通用的抽象类:
- public abstract class AbstractMockExecutor<T> {
- protected T mock;
- /**
- * @param clazz
- * @return
- */
- protected T createMock(Class<T> clazz) {
- mock = EasyMock.createMock(clazz);
- return mock;
- }
- public void execute() throws Exception {
- record();
- EasyMock.replay(mock);
- invoke();
- verify();
- }
- /**
- * 创建mock对象, 并对要mock的方法进行方法录制, 必须在该方法中手动调用{@link #createMock(Class)}方法.<br>
- * 该方法的一般做法如下:
- *
- * <pre>
- * createMock(MockClass);
- * EasyMock.expect(mock.mockMethod(mockArgument...)).andReturn(
- * mockResult);
- * BeanObject.setter(mock);
- * </pre>
- *
- * @throws Exception
- */
- protected abstract void record() throws Exception;
- /**
- * 调用经过mock之后的执行过程
- */
- protected abstract void invoke() throws Exception;
- /**
- * 验证mock是否正确
- */
- public void verify() {
- EasyMock.verify(mock);
- }
- }
2012-01 更新:
有时候我们会碰到这样的异常信息:
matcher calls were used outside expectations
后来在网上google了一把, 这里有个说明.
简单的说就是andReturn(xxx)中的xxx不能使用EasyMock.anyObject()这样的方法来指定结果. 但是它没有说解决办法. 这里可以利用andAnswer(), 比如这样写:
- final AtomicLong count = new AtomicLong(10000L);
- EasyMock.expect(db.count()).andAnswer(new IAnswer<Long>() {
- @Override
- public Long answer() throws Throwable {
- return count.getAndIncrement();
- }
- }).times(10);
easymock入门贴的更多相关文章
- EasyMock入门
这是一个JavaProject,有关EasyMock用法详见本文测试用例 首先是用到的实体类User.java package com.jadyer.model; public class User ...
- easymock快速入门
easymock是众多mock之中的很容易用的mock,今天刚开始学习,来个简单的教程.以购物车结算为例子,比如首先是每一个商品项的pojo. public class Item { private ...
- easymock+junit+spring学习·
Easymock学习 Author:luojie 1. Easymock简介 EasyMock 是一套通过简单的方法对于指定的 ...
- 前端入门20-JavaScript进阶之异步回调的执行时机
声明 本系列文章内容全部梳理自以下几个来源: <JavaScript权威指南> MDN web docs Github:smyhvae/web Github:goddyZhao/Trans ...
- 前端入门6-JavaScript客户端api&jQuery
本篇文章已授权微信公众号 dasu_Android(大苏)独家发布 声明 本系列文章内容全部梳理自以下四个来源: <HTML5权威指南> <JavaScript权威指南> MD ...
- PowerMock学习(一)之PoweMock的入门--模拟新增学生操作
关于powermock 在TDD领域Mock框架有很多,比如EasyMock,JMock,Mockito.可能有些同学会好奇了,为什么要重点把powermock拿出来呢,因为powermock可以解决 ...
- PowerMock学习之PoweMock的入门(二)
前言 在上一篇<PowerMock学习之PoweMock的入门(一)>文章中,已经简单提及一些关于powermock的用法,但是入门还未完,我还要坚持把它学习并坚持更新到博客中. Mock ...
- Mockito -- 入门篇
Mockito是一种mock工具/框架.我理解EasyMock有点过时了,Mockito是现在比较流行的. 什么是mock?说的直白一点,大家都知道unit test应该是尽可能独立的.对一个clas ...
- Angular2入门系列教程7-HTTP(一)-使用Angular2自带的http进行网络请求
上一篇:Angular2入门系列教程6-路由(二)-使用多层级路由并在在路由中传递复杂参数 感觉这篇不是很好写,因为涉及到网络请求,如果采用真实的网络请求,这个例子大家拿到手估计还要自己写一个web ...
随机推荐
- 关于jdbc收集
一.如果我这样获得一个resultset ResultSet rs=statment.execquery("select * from tab"我如何能够从resultset中获得 ...
- hdu 4381(背包变形)
题意: 给定n个块,编号从1到n,以及m个操作,初始时n个块是白色. 操作有2种形式: 1 ai xi : 从[1,ai]选xi个块,将这些块涂白. 2 ai xi:从[ai,n]选xi个块,将这些块 ...
- 把一个窗体嵌入到WinForm中进行显示,以CMD窗口为例
1.添加引用 using System.Runtime.InteropServices; 2. 加入以下代码段 [DllImport("User32.dll ", EntryPoi ...
- java定时器的几种用法
package com.lid; import java.util.Calendar; import java.util.Date; import java.util.Timer; import ja ...
- 使用SchemaSpy逆向工程生成数据库依赖关系使用SchemaSpy工具可以快速的从数据库中得到
使用SchemaSpy逆向工程生成数据库依赖关系 使用SchemaSpy工具可以快速的从数据库中得到表的依赖关系,同时生成一个生动的“表图”结合的报告.方便快速了解数据库中的数据库对象间关系,类 ...
- Delphi 注册文件类型 设置文件图标
{------------------------------------------------------------------------------- @过程名: slpert -& ...
- hihocoder 1356 分隔相同整数 简单贪心
分析:考虑贪心,考虑填ans[i],前i-1个合法,现在剩下一些数, 那么挑出出现次数最多的数,次数为mx,当前剩余总数为sum 如果sum-mx>=mx-1那么肯定有解,这个想想就知道了(这种 ...
- php获取网站根目录
php获取网站根目录方法一:<?phpdefine("WWWROOT",str_ireplace(str_replace("/","\\&quo ...
- selenium python (十一)alert/confirm/prompt的处理(js中的弹出框)
webdriver中处理js所生成的alert.confirm以及prompt,采用switch_to_alert()方法定位到alert/confirm/prompt.然后使用text/accept ...
- 顺序表的基本操作(C)
在顺序存储结构实现基本操作:初始化.创建.插入.删除.查找.遍历.逆置.合并运算. 运行示例: 请输入线性表La的长度: 请输入线性表La中的元素(共5个) *** 此时线性表La中的元素 *** * ...