Spring Boot集成测试中错误加载TestConfig问题咨询
问题原因
这是Spring Boot测试的上下文缓存机制导致的:
- Spring Boot为了提升测试效率,会把已创建的应用上下文缓存起来,当后续测试类的配置(比如
@SpringBootTest的classes、properties等参数)和缓存中的上下文匹配时,就会直接复用这个上下文。 - 你的第一个测试类
ILiveOrderHandlerImplTest加载了带@Primary注解的Mock版ApplicationEventPublisher,且该上下文被缓存。第二个测试类StockTraderServiceIntegrationTest的@SpringBootTest核心配置(如指定StockTraderApplication.class)和第一个高度相似,Spring便复用了缓存的上下文,导致Mock Bean被意外使用。
解决办法
可以通过以下几种方式解决:
1. 让两个测试的上下文缓存键不重复
给第二个测试类添加独特的properties参数,让Spring判定为不同上下文,从而创建新实例:
@ExtendWith(SpringExtension.class) @RunWith(SpringRunner.class) @SpringBootTest(classes = StockTraderApplication.class, properties = {"use_real_event_publisher=true"}) class StockTraderServiceIntegrationTest { // ... }
2. 标记第一个测试类执行后销毁上下文
在ILiveOrderHandlerImplTest上添加@DirtiesContext注解,让Spring在该测试执行完后销毁上下文,避免被后续测试复用:
@RunWith(SpringRunner.class) @SpringBootTest(classes = {StockTraderApplication.class, ILiveOrderHandlerImplTest.TestConfig.class}, properties = {"unit_test_no_external_services=true"}) @DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_CLASS) class ILiveOrderHandlerImplTest { // ... }
3. 给Mock Bean添加条件加载
修改TestConfig,让它只在特定属性开启时才加载,确保第二个测试不会触发该配置:
@TestConfiguration @ConditionalOnProperty(name = "unit_test_no_external_services", havingValue = "true") public static class TestConfig { @Bean @Primary public ApplicationEventPublisher applicationEventPublisherBean() { return Mockito.mock(ApplicationEventPublisher.class); } }
这样只有第一个测试(携带unit_test_no_external_services=true属性)会加载Mock Bean,第二个测试无该属性,就会使用真实Bean。
4. 第二个测试排除Mock配置类
在第二个测试的@SpringBootTest中明确排除TestConfig:
@ExtendWith(SpringExtension.class) @RunWith(SpringRunner.class) @SpringBootTest(classes = StockTraderApplication.class, exclude = ILiveOrderHandlerImplTest.TestConfig.class) class StockTraderServiceIntegrationTest { // ... }
内容的提问来源于stack exchange,提问作者Kannan J
相关产品推荐
相关产品推荐

