easyMock 使用总结

http://www.cnblogs.com/sequence/archive/2011/07/28/2119657.html

easyMock 使用总结

一、 准备

1. 引包

在maven的pom.xml加入依赖

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<dependency>
  
<groupId>junit</groupId>
  
<artifactId>junit</artifactId>
  
<version>3.8.1</version>
  
<scope>test</scope>
  
</dependency>
  
<dependency>
  
<groupId>org.easymock</groupId>
  
<artifactId>easymock</artifactId>
  
<version>3.0</version>
  
<scope>test</scope>
  
</dependency>
2. 要测试的类

新建 User类。

?
1
2
3
4
5
public class User {
  
String type;
  
}

新建 UserDao接口,里面有个insertUser(User user)方法。

?
1
2
3
4
5
public interface UserDao {
  
public boolean insertUser(User user);
  
}

新建 UserService类,里面有个registerUser(User user)方法。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public class UserServive {
  
private UserDao userDao;
  
public boolean registerUser(User user){
  
if (user.type.equals("vip")){
  
return userDao.insertUser(user);
  
}else {
  
System.out.println("only vip can be registered!");
  
Return false;
  
}
  
}
  
}

我们要测试 UserService的registerUser(User user)方法,但是这个方法依赖于UserDao的insertUser(User user)方法。我们假设UserDao这个接口现在还没写好,但是现在又想测UserService的方法逻辑,可它又依赖于UserDao,这可怎么测试?这时候就可以用mock技术啦。

测试代码如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
import junit.framework.TestCase;
  
import static org.easymock.EasyMock.*;
  
public class UserServiceTest extends TestCase{
  
private UserDao userDao;
  
private UserService userService = new UserService();
  
public void testRegisterUser() {
  
User user = new User();
  
user.type = "vip";
  
userDao = createMock(UserDao.class);
  
expect(userDao.insertUser(user)).andReturn(true);
  
replay(userDao);
  
userService.setUserDao(userDao);
  
assertEquals(true, userService.registerUser(user));
  
verify(userDao);
  
}
  
}

二、 一般步骤

1. 接口/类

easymock class extension的使用方式和普通的interface mock完全一致,基本上easymock中有的功能easymock class extension都同样提供,而且所有的类名和方法名都保持一致。

唯一的差异在于,easymock class extension的java package和easymock不同,easymock是

org.easymock.*, 而 easymock class extension是org.easymock.classextension.*,典型如

org.easymock.classextension.Easymock 对应 org.easymock.Easymock。另外在发布时,两者是分开发布的,easymock.jar 和 easymockclassextension.jar,需要根据需要分别导入,或者必要时同时导入。

不过3.0版本已经没有这个问题,接口与类是一样的。

2. record-replay-verify 模型
1) 创建mock对象
?
1
userDao = createMock(UserDao.class);
2) 记录mock对象期望的行为
?
1
expect(userDao.insertUser(user)).andReturn(true);

我们期望这个mock对象的方法被调用,同时给出我们希望这个方法返回的结果。这就是所谓的"记录mock对象上的操作", 同时我们也会看到"expect"这个关键字。总结说,在record阶段,我们需要给出的是我们对mock对象的一系列期望:若干个mock对象被调用,依从我们给定的参数,顺序,次数等,并返回预设好的结果(返回值或者异常).

3) 进入replay阶段
?
1
replay(userDao);

在replay阶段,我们关注的主要测试对象将被创建,之前在record阶段创建的相关依赖被关联到主要测试对象,然后执行被测试的方法,以模拟真实运行环境下主要测试对象的行为。

4) 对mock对象执行验证
?
1
verify(userDao);

验证交互行为,典型如依赖是否被调用,调用的参数,顺序和次数等。

三、 更多使用

1. 抛出异常
?
1
expect(userDao. insertUser (user)).andThrow(new SQLException("ID conflicts!"));
2. 调用次数

调用3次:expect(userDao. insertUser (user)).andReturn(true).times(3);

这里有一个官网文档中的例子:

?
1
2
3
4
5
6
7
expect(mock.voteForRemoval("Document"))
  
.andReturn((byte) 42).times(3)
  
.andThrow(new RuntimeException()).times(4)
  
.andReturn((byte) -42);

对于mock.voteForRemoval("Document")方法的调用,.andReturn((byte) 42).times(3) 表明前3次调用将返回42,.andThrow(new RuntimeException()).times(4)表示随后的4次调用(第4,5,6,7次)都将抛出异常,andReturn((byte) -42)表示第8次调用时将返回-42。

3. 调用void方法

如果mock对象的方法是void,则需要使用expectLastCall():

?
1
2
3
userDao.someVoidMethod();
  
Easymock.expectLastCall();

和Easymock.expect(***)一样,同样支持指定调用次数,抛出异常等:

4. 调用次序

Mock对象类型有三种

Normal — EasyMock.createMock() 默认mock出来的都是这个类型,只关心调用方法的参数,不关心调用的次序。

Strict — EasyMock.createStrictMock(): 当调用方法有次序要求的时候需要mock这个类型。

Nice — EasyMock.createNiceMock(): 调用到不期望的方法时不会使测试失败,如果原方法返回的类型是number的 它就会返回0,如果是boolean 它会返回false,如果是object它会返回null.

5. 参数匹配
?
1
2
3
// expect(userDao.insertUser(user)).andReturn(true);
  
expect(userDao.insertUser(EasyMock.<User>anyObject())).andReturn(true);

anyInt()、anyShort()、anyByte()、anyLong()、anyFloat()、anyDouble()、anyBoolean()、 matches(正则表达式)

6. Capture的使用

如果方法的参数实在无法预先确定,我们可以使用capture。比如UserService 有这么个方法:

?
1
2
3
4
5
6
7
8
9
public boolean registerVIP(){
  
User user = new User();
  
user.type = "VIP";
  
return userDao.insertUser(user);
  
}

当我们mock userDao的insertUser(user)方法时,我们无法确定他的参数会是什么样子的,因为参数是我们要测试的registerVIP这个方法new出来给他的,我们可以假定insertUser的方法逻辑的正确的,但是参数是registerVIP传给他的,所以我们得验证参数的正确性。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public void testRegisterVIP(){
  
userDao = createMock(UserDao.class);
  
Capture<User> captureUser = new Capture<User>();
  
expect(userDao.insertUser(capture(captureUser))).andReturn(true).times(2);
  
replay(userDao);
  
userService.setUserDao(userDao);
  
userService.registerVIP();
  
assertEquals("VIP", captureUser.getValue().type); //验证捕捉到的参数是否正确
  
assertEquals(true, userService.registerVIP());//验证最后的结果
  
verify(userDao);
  
}
7. 自定义参数匹配
?
1
//TODO!
8. 对象重用

为了避免生成过多的 Mock 对象,EasyMock 允许对原有 Mock 对象进行重用。要对 Mock 对象重新初始化,我们可以采用 reset 方法。和 replay 和 verify 方法类似,EasyMock 提供了两种 reset 方式:(1)如果 Mock 对象是由 org.easymock.EasyMock 类中的静态方法 createMock 生成的,那么该 Mock 对象的可以用 EasyMock 类的静态方法 reset 重新初始化;(2)如果 Mock 方法是由 IMocksControl 实例的 createMock 方法生成的,那么该 IMocksControl 实例方法 reset 的调用将会把所有该实例创建的 Mock 对象重新初始化。

在重新初始化之后,Mock 对象的状态将被置为 Record 状态。

9. 多个mock 用 MocksControl

当我们需要mock一系列对象的时候,如果每个都单独去mock很麻烦, 这种情况下可以考虑使用MocksControl来简化代码:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
IMocksControl mocksControl = createControl();
  
IMyInterface1 mock1 = mocksControl.createMock(IMyInterface1.class);
  
IMyInterface2 mock2 = mocksControl.createMock(IMyInterface2.class);
  
IMyInterface3 mock3 = mocksControl.createMock(IMyInterface3.class);
  
...
  
mocksControl.replay();
  
mocksControl.verify();
  
mocksControl.reset();
10. Class mocking的限制
1) 不能mock类的 final方法。如果final方法被调用,则只能执行原有的正常代码。
2) 不能mock类的static 方法。
3) 同样如果private方法被调用,只能执行原有的正常代码。
4) 不能mock类的一些特殊方法: equals(), toString()和hashCode().原因是easymock在实现是为每个class mock对象提供了内建的以上三个方法。需要强调的是,对于基于interface的mock,这个限制也是同样存在的,即使以上三个方式是interface定义的一部分。
5) 在使用时需要避开这种场景,或者组合使用其他的mock 框架比如jmockit来mock private方法和final方法。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
为了使用 EasyMock 发出 POST 请求,你可以按照以下步骤进行操作: 1. 首先,你需要创建一个模拟的 HTTP 请求对象。在 EasyMock 中,你可以使用 `org.easymock.EasyMock` 类的 `createMock` 方法创建该对象。 ```java import org.easymock.EasyMock; // 创建模拟的 HTTP 请求对象 HttpServletRequest request = EasyMock.createMock(HttpServletRequest.class); ``` 2. 接下来,你需要设置该请求对象的相关属性,例如请求方法、请求路径、请求参数等。 ```java // 设置请求方法为 POST EasyMock.expect(request.getMethod()).andReturn("POST").anyTimes(); // 设置请求路径 EasyMock.expect(request.getRequestURI()).andReturn("/your-api-endpoint").anyTimes(); // 设置请求参数 EasyMock.expect(request.getParameter("paramName")).andReturn("paramValue").anyTimes(); ``` 3. 然后,你需要创建一个模拟的 HTTP 响应对象,并设置相应的属性。 ```java // 创建模拟的 HTTP 响应对象 HttpServletResponse response = EasyMock.createMock(HttpServletResponse.class); // 设置响应状态码 response.setStatus(HttpServletResponse.SC_OK); // 设置响应内容类型 response.setContentType("application/json"); // 设置响应内容 response.getWriter().write("Response body"); ``` 4. 最后,你可以使用 `org.easymock.EasyMock` 类的 `replay` 和 `verify` 方法来启动和验证模拟对象。 ```java // 启动模拟对象 EasyMock.replay(request, response); // 执行你的代码逻辑,处理 POST 请求 // 验证模拟对象的方法是否按预期被调用 EasyMock.verify(request, response); ``` 通过以上步骤,你就可以使用 EasyMock 模拟一个 POST 请求,并进行相应的测试。请根据你的具体需求,适当修改代码中的请求路径、请求参数、响应状态码和响应内容等。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值