You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在测试环境初始化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"));
    }
}

关键说明

  1. 移除多余的Repository Mock:@WebMvcTest不需要加载Repository层,Mock Service后,Controller的调用会被隔离在Service层,不会触发真实的数据库操作。
  2. 用Mockito Stub Service方法:通过Mockito.when()指定Service方法的返回逻辑,模拟Service层的响应,这样就能测试Controller如何处理Service返回的数据并生成响应。
  3. 聚焦Controller测试目标:Controller测试的核心是验证请求的处理流程、响应状态码、响应内容是否符合预期,而非测试Repository的CRUD逻辑——后者属于Repository层的单元测试范畴。

内容的提问来源于stack exchange,提问作者der papa

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 05:15:38