Spring Boot服务层作者数据更新单元测试返回Null问题排查
Spring Boot服务层作者更新功能单元测试Null响应问题排查
问题描述
为Spring Boot服务层的作者数据更新功能编写单元测试时,执行发现response对象返回Null,导致测试失败。已mockauthorRepository的findById方法,但问题仍存在。
测试代码
@Test @DisplayName("Test 3: Author record Update successfully") @Order(3) void testUpdateAuthor_Success() { AuthorDTO authorDTO = new AuthorDTO(); authorDTO.setName("Updated Author Name"); Author existingAuthor = new Author(); existingAuthor.setId(1L); existingAuthor.setName("Original Author Name"); // Arrange Long authorId = 1L; lenient().when(authorRepository.findById(authorId)).thenReturn(Optional.of(existingAuthor)); // Act ResponseEntity<ApiResponse<String>> response = authorService.updateAuthor(existingAuthor.getId(), authorDTO); // Assert // verify(authorRepository).save(existingAuthor); assertEquals(HttpStatus.OK, response.getStatusCode()); assertEquals("Author record updated successfully.", Objects.requireNonNull(response.getBody()).getMessage()); assertEquals("Updated Author Name", existingAuthor.getName()); }
服务层代码
public ResponseEntity<ApiResponse<String>> updateAuthor(Long id, @Valid AuthorDTO authorDTO) { logger.info("Update a author ID : {} Author Dto : {}", id, authorDTO); try { logger.info("Check existingAuthor for ID :{}", id); Author existingAuthor = authorRepository.findById(id).orElse(null); if (existingAuthor != null) { logger.info("Updating author ID: {} author : {}", id, authorDTO); existingAuthor.setName(authorDTO.getName()); authorRepository.save(existingAuthor); logger.info("Updated author ID: {} author : {}", id, authorDTO); return ResponseUtil.buildResponse(null, "Author record updated successfully.", HttpStatus.OK); } else { logger.info("Author data not found or empty"); return ResponseUtil.buildResponse(null, "Author data not found.", HttpStatus.NOT_FOUND); } } catch (OptimisticLockingFailureException e) { return ResponseUtil.buildResponse(null, "Conflict: Author record was modified or deleted by another process: Author Id :" + id + "=>" + e, HttpStatus.CONFLICT); } catch (Exception e) { logger.error("Error occurred while updating author ID: {}", id, e); return ResponseUtil.buildResponse(null, "Error occurred while updating author with id: '" + id, HttpStatus.INTERNAL_SERVER_ERROR); } }
排查思路
- 检查Mock注入正确性:确认测试类中
authorRepository是通过@MockBean或@Mock+@InjectMocks正确注入到authorService中的,避免服务层使用真实Repository实例而非Mock对象。 - 验证Mock参数匹配:将Mock语句改为
when(authorRepository.findById(eq(authorId))).thenReturn(Optional.of(existingAuthor))(需导入org.mockito.ArgumentMatchers.eq),明确参数匹配规则,避免因参数类型或值的隐性不匹配导致Mock失效。 - 排查ResponseUtil工具类:临时替换服务层中
ResponseUtil.buildResponse的调用,直接返回new ResponseEntity<>(new ApiResponse<>(null, "Author record updated successfully."), HttpStatus.OK),若此时response不再为Null,说明工具类内部存在返回Null的逻辑问题。 - 检查异常分支执行情况:查看测试时的日志输出,确认是否进入了某个异常分支但返回的ResponseEntity为Null;或在服务层各return语句处添加断点,跟踪实际返回的对象是否正常。
- 移除lenient()测试:去掉
lenient(),使用普通的Mock语句,lenient()会放宽Mock的校验规则,可能掩盖参数匹配失败的问题。 - 确认参数传递正确性:在服务层
updateAuthor方法开头添加日志打印logger.info("Received update request for id: {}", id),确认接收到的id与Mock的id一致,避免参数传递过程中出现意外修改。
内容的提问来源于stack exchange,提问作者Gnanaseelan
相关产品推荐
相关产品推荐

