一、什么是Mockito
Mockito是一款用于java开发的mock测试框架,用于快速创建和配置mock对象。通过创建外部依赖的 Mock 对象, 然后将此 Mock 对象注入到测试类中,简化有外部依赖的类的测试。
假设我们需要对一个发奖系统服务做单元测试,服务的依赖关系如下:

为了完成RewardService的测试,我们需要去构建真实的DBService, CouponService, MemberService, 整个过程很长,涉及多个服务,数据构造工作比较繁琐困难。
这个时候,更简单快捷的方式就是通过mock的方式将依赖的服务使用虚拟的对象(即Mock的对象)来替代,直接mock出我们想要的数据来进行测试,方便快捷, 不需要关注那些的复杂的依赖了:

二、在springboot中使用Mockito
2.1 引入maven依赖
在项目pom.xml中引入依赖spring-boot-starter-test,内部就依赖了Mockito。
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> </dependency>

2.2 关键代码解析
1、添加注解,mock服务
//mockito注解, 用于启用Spring和Mockito @TestExecutionListeners(listeners = MockitoTestExecutionListener.class) public class RewardServiceTestMock{ //通过@MockBean注解,将TaskDubboService服务给mock掉 @MockBean private RewardDubboService rewardDubboService;
重要:首先,必须加这一行:@TestExecutionListeners(listeners = MockitoTestExecutionListener.class) ,用于启用Spring和Mockito,之前研究了半天用不起,报空指针,就是没有加这一行。
然后使用注解:@MockBean,把这个服务给mock掉。
2、mock接口返回内容
//mock接口返回内容 String msg1="[{\"class\":\"com.xxxx.RewardInfo\",\"rewardCount\":1,\"rewardName\":\"Mock请求1返回的奖励内容\"}]";
String msg1=xxxxxx, 这是定义你的接口返回内容。由于这个接口返回的内容是一个对象类型,所以还需要下面这句代码把String内容转换成指定的对象类型:
List<RewardInfo> mockResult1= JSONArray.parseArray(msg1,RewardInfo.class);
3、设置mock规则
Mockito.when(rewardDubboService.reward(ParamContext)).thenReturn(mockResult1);
表示当调用rewardService.reward(ParamContext)接口时,将接口的返回内容mock为之前定义的mockResult1的内容。
4、 调用接口
List<RewardInfo> result = rewardDubboService.reward(ParamContext); String resultStr = JSONObject.toJSONString(result);
整体代码如下:
//mockito注解, 用于启用Spring和Mockito @TestExecutionListeners(listeners = MockitoTestExecutionListener.class) public class RewardServiceTestMock{ //通过@MockBean注解,将TaskDubboService服务给mock掉 @MockBean private RewardDubboService rewardDubboService; //mock接口返回内容 String msg1="[{\"class\":\"com.xxxx.RewardInfo\",\"rewardCount\":1,\"rewardName\":\"Mock请求1返回的奖励内容\"}]"; //把String内容转换成指定的对象类型 List<RewardInfo> mockResult1= JSONArray.parseArray(msg1,RewardInfo.class); //设置mock规则 Mockito.when(rewardDubboService.reward(ParamContext)).thenReturn(mockResult1); //调用接口 List<RewardInfo> result = rewardDubboService.reward(ParamContext); String resultStr = JSONObject.toJSONString(result);
测试结果:

三.补充说明
@SpringBootTest @RunWith(SpringRunner.class) @TestExecutionListeners(listeners = MockitoTestExecutionListener.class) //step1 public class RuleRpcServiceTest extends KdAbstractJUnit4SpringContextTests { @Mock private OrderService orderService; //step2 @InjectMocks @Resource private UserServiceImpl userService; @Before public void init() { MockitoAnnotations.initMocks(this); } }
(1)@RunWith 指定运行环境,例: @RunWith(SpringRunner.class) Junit运行Spring的测试环境 @RunWith(MockitoJUnitRunner.class) Junit运行Mockito的运行环境,不会加载springboot上下文 @SpringBootTest 加载springboot上下文配置 (注意: @RunWith(MockitoJUnitRunner.class) 不能和 @RunWith(SpringRunner.class) 同时使用,而一般都需要 @RunWith(SpringRunner.class) 提供spring容器环境,所以很少用这个注解) (2)@Mock 用于模拟一个服务,例如: 测试的时候需用调用B服务,但是B服务没写 好,这是可以先Mock一个B服务 (3)@InjectMocks 标注服务的实现类 创建一个实例,其余用@Mock注解创建的mock将被注入到用该实例中 (4)@Before 每个测试方法执行前,执行一次 (5)@After 每个测试方法执行完,执行一次 (6)@Test 标注测试方法 (7)@MockBean : mock对应引入的bean
when…then和do…when用法
when…then:
//thenReturn 返回指定数据 when(userService.findById(userId)).thenReturn(new User(userId, null)); //触发上面mock定义的thenReturn User user1 = userService.findById(userId); System.out.println(user1); //thenCallRealMethod 调用mock类原本的方法 when(userService.findById(userId)).thenCallRealMethod();
do…when:
doReturn(new User(userId, null)).when(userService).findById(userId); doCallRealMethod().when(userService).findById(userId); doThrow(new RuntimeException("xxx不合法")).when(userService).findById(userId);
注入其它mock对象
如果一个mock对象中需要注入其它mock对象,比如要mock UserService,UserService 依赖于另一个mock对象orderService,这时就不能直接对 UserSiervice 使用 @Mock 直接的注解,需要:
- 标注 @InjectMocks + @Autowired之类的注入注解
@SpringBootTest @RunWith(SpringRunner.class) @TestExecutionListeners(listeners = MockitoTestExecutionListener.class) //step1 public class RuleRpcServiceTest extends KdAbstractJUnit4SpringContextTests { @Mock private OrderService orderService; //step2 @InjectMocks @Resource private UserServiceImpl userService; @Before public void init() { MockitoAnnotations.initMocks(this); } }