Spring Boot REST控制器单元测试:Mock时无法覆盖catch块问题
解决Spring Boot控制器单元测试catch块未覆盖问题
问题根源
- 参数匹配失败:测试中用具体
Text对象作为mock匹配条件,但控制器接收的是JSON反序列化生成的新Text对象,两者引用不同,导致Mockito未触发异常抛出。 - 冗余异常声明:控制器方法声明
throws IOException但内部已捕获该异常,属于不必要冗余,可能干扰测试逻辑。 - 多mock冲突:同时mock
Service接口和ServiceImpl实现类,易导致依赖注入混乱,控制器实际调用的不是测试mock的实例。
解决步骤
1. 修正控制器方法(规范代码)
去掉方法上的throws IOException,内部已捕获异常,无需向外抛出:
public ResponseEntity<ResponseSentence> getText(@RequestBody Text text) { try { return new ResponseEntity<>(serviceImpl.getText(text), HttpStatus.OK); } catch (IOException e) { return new ResponseEntity<>(HttpStatus.BAD_REQUEST); } }
2. 调整测试用例的mock参数匹配
使用any(Text.class)替代具体对象匹配,确保无论控制器接收的Text对象引用如何,都能触发异常:
@Autowired private MockMvc mockMvc; // 仅mock控制器实际依赖的bean,避免同时mock接口和实现类 @MockBean private ServiceImpl serviceImp; @Autowired private ObjectMapper objectMapper; @Test void getText_shouldReturnBadRequestWhenIOExceptionThrown() throws Exception { Text text = new Text(); text.setText(""); // 使用参数匹配器确保mock触发异常 when(serviceImp.getText(any(Text.class))).thenThrow(new IOException()); ResultActions response = mockMvc.perform(post("/opennlp/v1/sentence") .contentType(MediaType.APPLICATION_JSON) .content(objectMapper.writeValueAsString(text))); response.andDo(print()) .andExpect(status().isBadRequest()); Mockito.verify(serviceImp).getText(any(Text.class)); }
3. 额外排查点
- 确保控制器注入的bean类型与测试中mock的一致:若控制器依赖
Service接口,应mock接口而非实现类;反之则mock实现类。 - 检查代码覆盖率工具配置,确认未排除控制器类或测试类。
- 若需基于对象属性匹配,可给
Text类重写equals和hashCode方法,再使用eq(text)作为匹配条件。
内容的提问来源于stack exchange,提问作者xyzCoder
相关产品推荐
相关产品推荐

