Spring是否支持为每个@Test测试方法加载不同的application.properties文件?
解决方案
针对你需要为每个测试方法单独修改配置属性的需求,有两种无需单独创建测试类的实现方式:
方案1:方法级@TestPropertySource(推荐,Spring Boot 2.2+ 支持)
Spring Framework 5.2 及对应配套的 Spring Boot 2.2+ 版本开始,@TestPropertySource 注解支持直接标注在测试方法上,可直接指定要修改的单个属性值,完全匹配你的需求。
修改后的测试代码示例:
@RunWith(SpringRunner.class) @SpringBootTest public class ProtocolBeansTest { @Autowired private ApplicationContext applicationContext; @Test @TestPropertySource(properties = "PROTOCOL_DATA_TYPE = tcp") public void test1() { Assert.assertThrows(NoSuchBeanDefinitionException.class, () -> applicationContext.getBean(KafkaTopicConfig.class)); Assert.assertThrows(NoSuchBeanDefinitionException.class, () -> applicationContext.getBean(Producer.class)); Assert.assertThrows(NoSuchBeanDefinitionException.class, () -> applicationContext.getBean(Consumer.class)); Assert.assertNotNull(applicationContext.getBean(TcpConfig.class)); Assert.assertNotNull(applicationContext.getBean(MyController.class)); Assert.assertNotNull(applicationContext.getBean(ScheduledTasks.class)); } @Test @TestPropertySource(properties = "PROTOCOL_DATA_TYPE = kafka") public void testKafkaBeansAreOnOthersAreOff() { Assert.assertThrows(NoSuchBeanDefinitionException.class, () -> applicationContext.getBean(TcpConfig.class)); Assert.assertThrows(NoSuchBeanDefinitionException.class, () -> applicationContext.getBean(KokosProtoController.class)); Assert.assertThrows(NoSuchBeanDefinitionException.class, () -> applicationContext.getBean(ScheduledTasks.class)); Assert.assertNotNull(applicationContext.getBean(KafkaTopicConfig.class)); Assert.assertNotNull(applicationContext.getBean(Producer.class)); Assert.assertNotNull(applicationContext.getBean(Consumer.class)); } @Test @TestPropertySource(properties = "PROTOCOL_DATA_TYPE = none") public void test3() { Assert.assertThrows(NoSuchBeanDefinitionException.class, () -> applicationContext.getBean(TcpConfig.class)); Assert.assertThrows(NoSuchBeanDefinitionException.class, () -> applicationContext.getBean(KokosProtoController.class)); Assert.assertThrows(NoSuchBeanDefinitionException.class, () -> applicationContext.getBean(ScheduledTasks.class)); Assert.assertThrows(NoSuchBeanDefinitionException.class, () -> applicationContext.getBean(KafkaTopicConfig.class)); Assert.assertThrows(NoSuchBeanDefinitionException.class, () -> applicationContext.getBean(Producer.class)); Assert.assertThrows(NoSuchBeanDefinitionException.class, () -> applicationContext.getBean(Consumer.class)); } @TestConfiguration @ConditionalOnProperty(value = PROTOCOL_DATA_TYPE, havingValue = KAFKA_PROTOCOL_TYPE) public static class SomeServiceMockConfig { @MockBean private static KafkaTopicConfig kafkaTopicConfig; } }
方案2:嵌套测试类(兼容低版本Spring Boot)
如果你的Spring Boot版本低于2.2,不支持方法级@TestPropertySource,可以用JUnit的@Nested注解创建嵌套测试类,每个嵌套类对应一套配置,所有测试都在同一个外层类中,无需创建独立测试文件。
代码示例:
@RunWith(SpringRunner.class) @SpringBootTest public class ProtocolBeansTest { @Nested @TestPropertySource(properties = "PROTOCOL_DATA_TYPE = tcp") class TcpProtocolTest { @Autowired private ApplicationContext applicationContext; @Test public void test1() { // 原test1逻辑不变 } } @Nested @TestPropertySource(properties = "PROTOCOL_DATA_TYPE = kafka") class KafkaProtocolTest { @Autowired private ApplicationContext applicationContext; @Test public void testKafkaBeansAreOnOthersAreOff() { // 原kafka测试逻辑不变 } } @Nested @TestPropertySource(properties = "PROTOCOL_DATA_TYPE = none") class NoneProtocolTest { @Autowired private ApplicationContext applicationContext; @Test public void test3() { // 原test3逻辑不变 } } @TestConfiguration @ConditionalOnProperty(value = PROTOCOL_DATA_TYPE, havingValue = KAFKA_PROTOCOL_TYPE) public static class SomeServiceMockConfig { @MockBean private static KafkaTopicConfig kafkaTopicConfig; } }
注意事项
- 两种方案都会为每个测试方法/嵌套类单独初始化Spring上下文,可添加
@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD)注解及时清理上下文,避免不同测试间的配置互相干扰。 - 以上两种方式都无需修改原业务配置逻辑,仅通过测试层注解即可实现单属性的自定义修改。
内容的提问来源于stack exchange,提问作者Mica Straus
相关产品推荐
相关产品推荐

