如何在测试环境初始化Repository?Controller测试遇空指针问题
问题原因与解决方案
你在测试中直接调用todoRepository.save()报错,是因为@MockBean注解生成的是Mock对象,这类对象默认所有方法都没有实际逻辑,调用后会返回null或空值,而且你的测试逻辑本身就偏离了Controller单元测试的目标。
核心问题分析
@WebMvcTest是专门用于Controller层单元测试的注解,它只会加载与目标Controller相关的上下文。你的测试目标是验证Controller的接口行为,因此只需要Mock Controller直接依赖的TodoService即可,不需要直接操作ToDoRepository——因为Service已经被Mock,它内部对Repository的调用不会触发真实逻辑,也不需要你手动初始化Repository。
修正后的测试代码示例
@ExtendWith(SpringExtension.class) @WebMvcTest(value = TodoController.class) @WithMockUser public class TodoControllerTest { @Autowired private MockMvc mockMvc; @MockBean private TodoService todoService; // 移除不需要的@MockBean ToDoRepository @Test public void retrieveDetailsForEintrag() throws Exception { // 1. 准备测试用的Todo对象 Todo mockTodo = new Todo("Drink", "01.11.2022"); // 2. Mock Service的方法,指定调用时的返回值 // 假设Controller调用的是todoService.getTodoById(),请根据实际方法调整 Mockito.when(todoService.getTodoById(Mockito.anyLong())).thenReturn(mockTodo); // 3. 用MockMvc发送请求,验证接口响应 mockMvc.perform(get("/todos/1") .contentType(MediaType.APPLICATION_JSON)) .andExpect(status().isOk()) .andExpect(jsonPath("$.title").value("Drink")) .andExpect(jsonPath("$.date").value("01.11.2022")); } }
关键说明
- 移除多余的Repository Mock:
@WebMvcTest不需要加载Repository层,Mock Service后,Controller的调用会被隔离在Service层,不会触发真实的数据库操作。 - 用Mockito Stub Service方法:通过
Mockito.when()指定Service方法的返回逻辑,模拟Service层的响应,这样就能测试Controller如何处理Service返回的数据并生成响应。 - 聚焦Controller测试目标:Controller测试的核心是验证请求的处理流程、响应状态码、响应内容是否符合预期,而非测试Repository的CRUD逻辑——后者属于Repository层的单元测试范畴。
内容的提问来源于stack exchange,提问作者der papa
相关产品推荐
相关产品推荐

