JMock是一个使用模拟对象机制测试Java代码的开发包。模拟对象(Mock Object)可以取代真实对象的位置,用于测试一些与真实对象进行交互或依赖于真实对象的功能,模拟对象的背后目的就是创建一个轻量级的、可控制的对象来代替测试中需要的真实对象,模拟真实对象的行为和功能,方便我们的测试。JMock 就是这种机制的实现,使用 JMock 我们可以快速创建模拟对象,定义交互过程中的约束条件等,同时 JMock 也是易扩展的,你可以很方便添加自定义的需求。
(1)创建JMock上下文,例如:
Mockery context = new Mockery();
(2)根据接口创建模拟对象,例如:
final UserService userService = context.mock(UserService.class);
(3)在JMock上下文中创建我们的期望,即要依赖的服务。例如:
context.checking(new Expectations() { { // 当订单ID为100时,执行该期望 oneOf(userService).getUserInfo(100); will(returnValue("orderId=100")); // 返回值 // 当订单ID为200时,执行该期望 oneOf(userService).getUserInfo(200); will(returnValue("orderId=200")); // 返回值 } });
上面定义了两个期望,第一个当订单ID=100时被调用;第二个期望当订单ID=200时被调用,两个期望被调用时将返回值。
(4)使用模拟对象调用目标服务。
假如我们有一个订单服务和一个用户服务,但是这两个服务分别位于不同的模块中,同时这两个模块由两个不同的团队进行开发。其中,订单服务需要依赖用户服务,但是用户服务还没有开发完成;在实际开发中不可能去等待用户服务开发完成后再去开发订单服务。因此,我们需要使用 jmock 框架来模拟用户服务。下面将通过一个实例来讲解怎样使用 jmock 来模拟用户服务:
用户服务接口(UserService.java)定义如下:
/** * 用户服务 * @author huangxin 2019/11/2 */ public interface UserService { /** * 根据订单ID获取下订单的用户信息 * @param orderId 订单ID * @return */ String getUserInfo(int orderId); }
订单服务(OrderService.java)定义如下:
/** * 订单服务 * @author huangxin 2019/11/2 */ public class OrderService { private UserService userService; // 依赖用户服务 public void setUserService(UserService userService) { this.userService = userService; } /** * 根据订单ID查找订单 * @param orderId 订单ID */ public void findOrder(int orderId) { System.out.println("OrderService - 开始查找订单 " + orderId); // 获取用户信息 System.out.println(userService.getUserInfo(orderId)); System.out.println("OrderService - 完成订单查找 " + orderId + "\n\n"); } }
用户实体定义(User.java)如下:
/** * 用户对象 * @author huangxin 2019/11/2 */ public class User { private int id; private String name; public User() { } public User(int id, String name) { this.id = id; this.name = name; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public String toString() { return "User{" + "id=" + id + ", name='" + name + '\'' + '}'; } }
测试客户端如下:
/** * 客户端 * @author huangxin 2019/11/2 */ public class Client { public static void main(String[] args) { // 建立一个 test 上下文对象 Mockery context = new Mockery(); // 生成一个mock对象 final UserService userService = context.mock(UserService.class); // 设置期望 context.checking(new Expectations() { { // 当订单ID为100时,执行该期望 oneOf(userService).getUserInfo(100); will(returnValue("orderId=100")); // 当订单ID为200时,执行该期望 oneOf(userService).getUserInfo(200); will(returnValue("orderId=200")); } }); // 创建订单服务对象 OrderService orderService = new OrderService(); orderService.setUserService(userService); orderService.findOrder(100); orderService.findOrder(200); } }
跟多关于jmock的文章请阅读后续文章。