我正在准备一个 Spring Boot 启动器(用于测试),我希望允许最终用户通过一些测试替身轻松更改生产代码。这些应该是模块化和独立的,即:
- 在一项 IT 中,我想模拟 Java 8
Clock @Bean
,我用它来检索系统时间(通过ZonedDateTime.now(clock)
- 在其他模拟身份验证服务中
- 第三个同时进行
我当前的解决方案基于具有 @Profile
和 @Primary @Bean
的 AutoConfiguration
类:
@Configuration
@Profile("testClock")
public class FixedClockConfiguration {
@Value("${neostarter.test.clock:2010-01-10T10:00:00Z}")
private String fixedClock;
@Bean
@Primary
Clock clock() {
return Clock.fixed(Instant.parse(fixedClock), TimeZone.getDefault().toZoneId());
}
}
然后,要使用它,我需要在 IT 中设置 @ActiveProfiles
并提供时钟值(如果我不喜欢 @TestPropertySource
的默认值):
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(Application.class)
@WebIntegrationTest
@ActiveProfiles("testClock")
@TestPropertySource(properties = "neostarter.test.clock=2015-05-05T10:00:00Z")
public class IntegrationTest {
相同的模式将适用于我的 IT 中的所有测试替身,因此我需要添加更多 Activity 配置文件(以及可能的一些测试属性):
@ActiveProfiles({"testClock", "testAuth"})
有什么方法可以将其转换为基于注释的解决方案吗?我想要实现的是一组简单的注释:
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(Application.class)
@WebIntegrationTest
@TestClock("2015-05-05T10:00:00Z")
@TestAuth(roles = {"admin", "user"})
public class IntegrationTest {
它会做同样的事情(或者最终结果是相同的),其中@TestClock
和@TestAuth
是完全独立和可选的。
最佳答案
在 Spring Boot 1.3 中,没有特别简单的方法可以做到这一点。也许您最好的选择是将注释从测试类转移到配置,例如:
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration
public class ExampleTests {
@Autowired
private Clock clock;
@Test
public void test() throws Exception {
System.out.println(this.clock);
}
@Configuration
@Import(SampleSimpleApplication.class)
@TestClock("2015-05-05T10:00:00Z")
static class Config {
}
}
然后您可以让@TestClock
导入注册器:
@Retention(RetentionPolicy.RUNTIME)
@Import(TestClockRegistrar.class)
public @interface TestClock {
String value();
}
注册商读取注释并创建 bean:
public class TestClockRegistrar implements ImportBeanDefinitionRegistrar {
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata,
BeanDefinitionRegistry registry) {
String pattern = (String) importingClassMetadata
.getAnnotationAttributes(TestClock.class.getName()).get("value");
BeanDefinition beanDefinition = new RootBeanDefinition(Clock.class);
beanDefinition.setFactoryMethodName("fixed");
Instant instant = Instant.parse(pattern);
ZoneId zone = TimeZone.getDefault().toZoneId();
beanDefinition.getConstructorArgumentValues().addIndexedArgumentValue(0, instant);
beanDefinition.getConstructorArgumentValues().addIndexedArgumentValue(1, zone);
registry.registerBeanDefinition("clock", beanDefinition);
}
}
当然,我不确定这比简单地删除所有注释要好得多:
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration
public class ExampleTests {
@Autowired
private Clock clock;
@Test
public void test() throws Exception {
System.out.println(this.clock);
}
@Configuration
@Import(SampleSimpleApplication.class)
static class Config {
@Bean
@Primary
public Clock clock() {
Clock.fixed(...)
}
}
}
我们正在积极研究为 Spring Boot 1.4 提供更好的模拟支持。您可以关注https://github.com/spring-projects/spring-boot/issues/5042为了进步。
关于java - Spring Boot 集成测试通过注释加倍?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35848467/