@WebMvcTest测试含@Autowired构造方法的WebConfig时Bean缺失问题
问题分析与解决方案
这个问题的核心在于**@WebMvcTest是Spring的切片测试注解,它只会加载与Web层相关的最小化上下文**——比如你的OnlineDateController、Spring MVC的基础配置,但不会自动加载@ConfigurationProperties类,也不会自动处理配置类的依赖注入。你的WebConfig依赖OriginAllowedUrisProperties,但这个bean并没有被纳入测试上下文,所以抛出了依赖缺失的异常。
先规范配置类(可选但推荐)
首先,你的OriginAllowedUrisProperties注解有点冗余:@Configuration和@Component不需要同时使用,@ConfigurationProperties配合@Component就可以让Spring扫描并注册它,或者更规范的方式是用@EnableConfigurationProperties来显式注册:
// 修正后的配置属性类 @Component @ConfigurationProperties(prefix = "origins") public class OriginAllowedUrisProperties { private String[] allowedUris; // Getter和Setter }
解决方案选择
方案1:加载真实的配置属性与WebConfig
如果你需要在测试中使用真实的CORS配置(比如从application-test.yml读取),可以在测试类中添加两个注解:
@EnableConfigurationProperties(OriginAllowedUrisProperties.class):告诉Spring在测试上下文里启用这个配置属性类@Import(WebConfig.class):显式导入你的Web配置类
修改后的测试类:
@ExtendWith(SpringExtension.class) @WebMvcTest(OnlineDateController.class) @EnableConfigurationProperties(OriginAllowedUrisProperties.class) @Import(WebConfig.class) // 如果需要加载特定环境的配置文件,加上这个 @ActiveProfiles("test") class TestOnlineDateController { @MockBean private OnlineDateService onlineDateService; @Autowired private MockMvc mockMvc; @Test void testGetOnlineDate() throws Exception { when(onlineDateService.findOnlineDates()).thenReturn( Collections.singletonList(new OnlineDate())); mockMvc.perform( get("/onlineDates") .accept(MediaType.APPLICATION_JSON)) .andExpect(status().isOk()) .andExpect(JSON_ONLINE_DATE_MATCHER) .andDo(print()); } }
方案2:Mock配置属性类(适合仅测试Controller逻辑)
如果你的测试不需要验证CORS逻辑,只是想测试Controller的接口响应,可以直接MockOriginAllowedUrisProperties,这样WebConfig就能被正常实例化:
@ExtendWith(SpringExtension.class) @WebMvcTest(OnlineDateController.class) class TestOnlineDateController { @MockBean private OnlineDateService onlineDateService; @MockBean private OriginAllowedUrisProperties originAllowedUrisProperties; @Autowired private MockMvc mockMvc; @BeforeEach void setup() { // 可选:设置mock的返回值,模拟配置的允许域名 when(originAllowedUrisProperties.getAllowedUris()) .thenReturn(new String[]{"http://localhost:3000"}); } @Test void testGetOnlineDate() throws Exception { when(onlineDateService.findOnlineDates()).thenReturn( Collections.singletonList(new OnlineDate())); mockMvc.perform( get("/onlineDates") .accept(MediaType.APPLICATION_JSON)) .andExpect(status().isOk()) .andExpect(JSON_ONLINE_DATE_MATCHER) .andDo(print()); } }
为什么之前的尝试无效?
- 仅添加
@ContextConfiguration(classes = {WebConfig.class}):虽然加载了WebConfig,但它依赖的OriginAllowedUrisProperties并没有被Spring测试上下文注册——因为@WebMvcTest不会自动处理@ConfigurationProperties类。 - 使用
@Filter排除配置:这种操作反而可能移除了必要的上下文组件,没有从根本上解决依赖缺失的问题。
总结
- 如果需要验证CORS相关的逻辑,选择方案1,加载真实的配置属性;
- 如果只是测试Controller的业务接口响应,选择方案2,Mock依赖更简洁高效。
内容的提问来源于stack exchange,提问作者Philschke
相关产品推荐
相关产品推荐

