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

JUnit4转JUnit5:@RunWith改@ExtendWith后Spring Boot测试报错求助

解决JUnit5迁移中@WebMvcTest与Mockito混用导致的Bean找不到问题

我来帮你理清楚这个问题的根源,以及对应的解决方案:

问题根源分析

你遇到的NoSuchBeanDefinitionException主要是因为以下几个冲突和使用不当:

  1. @WebMvcTest的作用范围:这个注解是Spring Boot的「测试切片」,它只会加载Web层相关的Bean(比如你的HappyPostController),不会自动加载业务层的HappyPostService。但你的控制器通过构造器依赖HappyPostService,Spring容器启动时找不到这个Bean,所以报错。
  2. 测试方式混用:你同时用了Spring的@WebMvcTest(会自动装配控制器)和Mockito的@Mock/@InjectMocks(手动创建控制器),两种方式互相冲突——Spring还是会尝试初始化容器内的控制器实例,但找不到依赖的Service。
  3. 弃用属性:@WebMvcTest的secure=false已经被弃用,虽然不是当前报错的原因,但后续建议替换成@AutoConfigureMockMvc(secure = false)。

解决方案一:Spring官方推荐的Web层测试方式(@WebMvcTest + @MockBean)

这是最贴合Spring Boot测试最佳实践的方案,用@MockBean让Spring自动创建并注入Mock的Service到控制器中,不需要手动构建控制器和MockMvc:

@ExtendWith(SpringExtension.class)
@WebMvcTest(HappyPostController.class)
// 替代弃用的secure=false,关闭安全校验
@AutoConfigureMockMvc(secure = false)
public class HappyPostControllerTest {
    // Spring自动配置MockMvc
    @Autowired
    private MockMvc mockMvc;

    // 让Spring创建一个Mock的Service并加入容器,自动注入到控制器
    @MockBean
    private HappyPostServiceImpl happyPostService;

    // Spring自动注入控制器实例(已经包含Mock的Service)
    @Autowired
    private HappyPostController happyPostController;

    @Test
    public void testMockCreation() {
        Assertions.assertNotNull(happyPostService);
        Assertions.assertNotNull(mockMvc);
        Assertions.assertNotNull(happyPostController);
    }

    // 示例:测试接口返回
    @Test
    public void testGetHappyPostSuccess() throws Exception {
        // Mock Service的返回值
        HappyPost mockPost = new HappyPost();
        mockPost.setId(1L);
        mockPost.setTitle("Test Happy Post");
        when(happyPostService.getPostById(1L)).thenReturn(mockPost);

        // 执行请求并验证结果
        mockMvc.perform(get("/posts/1")
                        .contentType(MediaType.APPLICATION_JSON))
                .andExpect(status().isOk())
                .andExpect(jsonPath("$.id").value(1L))
                .andExpect(jsonPath("$.title").value("Test Happy Post"));
    }
}

解决方案二:纯Mockito手动测试(不加载Spring容器)

如果你想完全脱离Spring容器,只测试控制器逻辑,可以去掉Spring相关的测试注解,手动构建MockMvc:

@TestInstance(TestInstance.Lifecycle.PER_CLASS)
public class HappyPostControllerTest {
    private MockMvc mockMvc;

    @Mock
    private HappyPostServiceImpl happyPostService;

    private HappyPostController happyPostController;

    @BeforeAll
    public void initialize() {
        // 替换弃用的initMocks,初始化Mockito环境
        MockitoAnnotations.openMocks(this);
        // 手动创建控制器,注入Mock的Service
        happyPostController = new HappyPostController(happyPostService);
        // 构建独立的MockMvc
        this.mockMvc = MockMvcBuilders
                .standaloneSetup(happyPostController)
                .build();
    }

    @Test
    public void testMockCreation() {
        Assertions.assertNotNull(happyPostService);
        Assertions.assertNotNull(mockMvc);
        Assertions.assertNotNull(happyPostController);
    }

    // 其他测试方法...
}

额外注意点

  • 方案一的优势是能自动配置Web层的各种组件(比如消息转换器、全局异常处理器),测试更贴近真实运行环境。
  • 方案二更轻量,适合快速验证控制器的核心逻辑,不需要启动Spring容器。
  • 注意MockitoAnnotations.initMocks(this)已被弃用,建议使用MockitoAnnotations.openMocks(this)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 04:17:06