使用JUnit参数化测试时MockMvc注入为空的问题排查
解决JUnit参数化测试中MockMvc注入为null的问题
方案一:改用JUnit 5参数化测试(推荐)
JUnit 5采用扩展模型,无需替换测试运行器,可与Spring Boot测试注解完美兼容,直接实现依赖注入+参数化测试。
修改测试类代码如下:
@SpringBootTest @AutoConfigureMockMvc class BadgeControllerIT { @Resource private MockMvc mockMvc; @ParameterizedTest @MethodSource("testInputs") void badgeControllerTests(MultiValueMap<String, String> params, String expectedBadgeAsSVG, ResultMatcher status) throws Exception { mockMvc .perform( get("/api/badge") .queryParams(params) .accept("image/svg+xml") ) .andExpect(status) .andExpect(content().string(expectedBadgeAsSVG)); } static Stream<Arguments> testInputs() { // 适配原有测试用例数组,转为JUnit 5的Arguments流 return Arrays.stream(BadgeControllerTestsInputProvider.TEST_INPUTS) .map(Arguments::of); } }
注意事项:
- Spring Boot 2.2+版本的
spring-boot-starter-test默认包含JUnit 5,无需额外引入依赖 - 测试类无需添加
@RunWith注解 - 原
BadgeControllerTestsInputProvider类可保持不变
方案二:JUnit 4下手动初始化Spring上下文
如果必须使用JUnit 4,可通过TestContextManager手动触发Spring上下文初始化和依赖注入,解决MockMvc/WebApplicationContext为null的问题:
修改测试类代码如下:
@RunWith(Parameterized.class) @SpringBootTest @AutoConfigureMockMvc public class BadgeControllerIT { private TestContextManager testContextManager; @Resource private MockMvc mockMvc; private final MultiValueMap<String, String> params; private final String expectedBadgeAsSVG; private final ResultMatcher status; public BadgeControllerIT(MultiValueMap<String, String> params, String expectedBadgeAsSVG, ResultMatcher status) { this.params = params; this.expectedBadgeAsSVG = expectedBadgeAsSVG; this.status = status; } @Before public void setUp() throws Exception { // 手动初始化Spring测试上下文,触发依赖注入 testContextManager = new TestContextManager(getClass()); testContextManager.prepareTestInstance(this); } @Parameterized.Parameters public static Collection<Object[]> parameters() { return Arrays.asList(BadgeControllerTestsInputProvider.TEST_INPUTS); } @Test public void badgeControllerTests() throws Exception { mockMvc .perform( get("/api/badge") .queryParams(params) .accept("image/svg+xml") ) .andExpect(status) .andExpect(content().string(expectedBadgeAsSVG)); } }
问题根源
JUnit 4的@RunWith注解只能指定一个测试运行器,当使用Parameterized.class时,会替换Spring的SpringJUnit4ClassRunner,导致Spring无法自动初始化上下文、完成依赖注入,最终MockMvc等Bean为null。
内容的提问来源于stack exchange,提问作者Soroush Shemshadi
相关产品推荐
相关产品推荐

