如何用JUnit Mock测试Controller与Service层的新增记录方法?
问题描述
我想给Service层和Repository中新增数据库记录的方法编写Mock单元测试,但不知道正确操作方式,还遇到了报错。
现有代码
Controller代码
@PostMapping("/altaDiaInhabil") private void addWorkingDay(@RequestBody CatDiaEntity day) throws Exception { try { catDiaInhabilService.addNewWorkingDay(day); } catch (Exception e) { LOGGER.error("Error in CatDiaEntity Values "); throw e; } }
ServiceImpl代码
@Transactional @Override public void addNewWorkingDay(CatDiaEntity dayOff) throws Exception { try { catDiaRepository.saveWorkingDay(dayOff.getFechaInb(), dayOff.getDescDiaInb(), dayOff.getInhaMx(), dayOff.getInhabCh()); } catch (Exception e) { LOGGER.error("An error ocurred to insert CatDiaEntity Data"); } }
遇到的报错
The method when in the type Mockito is not applicable for the arguments void
我编写的测试代码
@Mock private CatDiaRepository catDiaRepository; @InjectMocks private CatDiaServiceImpl serviceImpl; @BeforeEach public void init() { MockitoAnnotations.openMocks(this); catDiEnatity = new CatDiaEntity(); } @Test public void testAddNewRecord() { catDiEnatity.setFechaInb("12/12/24"); catDiEnatity.setDescDiaInb("New day"); catDiEnatity.setInhaMx("1"); catDiEnatity.setInhabCh("0"); Mockito.when(catDiaRepository.saveWorkingDay(catDiEnatity.getFechaInb(), catDiEnatity.getDescDiaInb(), catDiEnatity.getInhaMx(), catDiEnatity.getInhabCh())).thenReturn(); }
请问如何正确测试这两个方法?
解决方案
一、Service层单元测试(解决报错)
报错原因是saveWorkingDay是**无返回值(void)**方法,Mockito的when()只适用于有返回值的方法。针对void方法,需改用doNothing()或doThrow()来模拟行为:
正确的Service测试代码
@Mock private CatDiaRepository catDiaRepository; @InjectMocks private CatDiaServiceImpl serviceImpl; private CatDiaEntity catDiaEntity; @BeforeEach public void init() { MockitoAnnotations.openMocks(this); catDiaEntity = new CatDiaEntity(); } @Test public void testAddNewRecord_Success() throws Exception { // 准备测试数据 catDiaEntity.setFechaInb("12/12/24"); catDiaEntity.setDescDiaInb("New day"); catDiaEntity.setInhaMx("1"); catDiaEntity.setInhabCh("0"); // 模拟Repository的void方法正常执行 Mockito.doNothing().when(catDiaRepository) .saveWorkingDay(catDiaEntity.getFechaInb(), catDiaEntity.getDescDiaInb(), catDiaEntity.getInhaMx(), catDiaEntity.getInhabCh()); // 调用Service方法 serviceImpl.addNewWorkingDay(catDiaEntity); // 验证Repository方法是否按预期调用 Mockito.verify(catDiaRepository, Mockito.times(1)) .saveWorkingDay("12/12/24", "New day", "1", "0"); } // 可选:测试异常场景 @Test public void testAddNewRecord_Exception() throws Exception { catDiaEntity.setFechaInb("12/12/24"); // 模拟Repository抛出异常 Mockito.doThrow(new RuntimeException("DB error")).when(catDiaRepository) .saveWorkingDay(anyString(), anyString(), anyString(), anyString()); // 调用Service方法(内部会捕获异常) serviceImpl.addNewWorkingDay(catDiaEntity); // 验证Repository方法被调用 Mockito.verify(catDiaRepository, Mockito.times(1)) .saveWorkingDay("12/12/24", null, null, null); }
核心说明:
doNothing():模拟void方法正常执行,无额外操作verify():验证Mock对象的方法调用次数、参数匹配情况,这是void方法测试的核心验证逻辑anyString()是Mockito参数匹配器,用于模糊匹配参数
二、Controller层单元测试
Controller层测试需用MockMvc模拟HTTP请求,同时Mock依赖的Service层:
Controller测试代码示例
@WebMvcTest(CatDiaController.class) public class CatDiaControllerTest { @Autowired private MockMvc mockMvc; @MockBean private CatDiaInhabilService catDiaInhabilService; @Test public void testAddWorkingDay_Success() throws Exception { // 准备请求体数据 CatDiaEntity requestBody = new CatDiaEntity(); requestBody.setFechaInb("12/12/24"); requestBody.setDescDiaInb("New day"); requestBody.setInhaMx("1"); requestBody.setInhabCh("0"); // 模拟Service方法无异常执行 Mockito.doNothing().when(catDiaInhabilService).addNewWorkingDay(requestBody); // 发送POST请求并验证响应 mockMvc.perform(MockMvcRequestBuilders.post("/altaDiaInhabil") .contentType(MediaType.APPLICATION_JSON) .content(new ObjectMapper().writeValueAsString(requestBody))) .andExpect(MockMvcResultMatchers.status().isOk()); // 验证Service方法被调用 Mockito.verify(catDiaInhabilService, Mockito.times(1)).addNewWorkingDay(requestBody); } @Test public void testAddWorkingDay_Exception() throws Exception { CatDiaEntity requestBody = new CatDiaEntity(); // 模拟Service抛出异常 Mockito.doThrow(new Exception("Invalid data")).when(catDiaInhabilService).addNewWorkingDay(any(CatDiaEntity.class)); // 发送请求并验证异常响应 mockMvc.perform(MockMvcRequestBuilders.post("/altaDiaInhabil") .contentType(MediaType.APPLICATION_JSON) .content(new ObjectMapper().writeValueAsString(requestBody))) .andExpect(MockMvcResultMatchers.status().isInternalServerError()); // 验证Service方法被调用 Mockito.verify(catDiaInhabilService, Mockito.times(1)).addNewWorkingDay(requestBody); } }
核心说明:
@WebMvcTest:专门用于Controller层测试,自动配置MockMvc@MockBean:Mock Controller依赖的Service对象MockMvc:模拟HTTP请求,验证响应状态、内容等
内容的提问来源于stack exchange,提问作者Root93
相关产品推荐
相关产品推荐

