Java Spring引导集成测试按注释加倍?
我正在准备一个springbootstarter(用于测试),我想让最终用户可以通过一些测试来轻松地修改生产代码。这些应是模块化和独立的,即:Java Spring引导集成测试按注释加倍?,java,spring,spring-boot,spring-test,Java,Spring,Spring Boot,Spring Test,我正在准备一个springbootstarter(用于测试),我想让最终用户可以通过一些测试来轻松地修改生产代码。这些应是模块化和独立的,即: 在其中一个例子中,我想模拟Java8Clock@Bean,我使用它来检索系统时间(通过ZoneDateTime.now(时钟) 在其他模拟身份验证服务中 在第三种情况下,两者都要做 我当前的解决方案基于具有@Profile和@Primary@Bean的自动配置类: @Configuration @Profile("testClock") public
- 在其中一个例子中,我想模拟Java8
,我使用它来检索系统时间(通过Clock@Bean
ZoneDateTime.now(时钟)
- 在其他模拟身份验证服务中
- 在第三种情况下,两者都要做
@Profile
和@Primary@Bean
的自动配置
类:
@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中的所有测试加倍,因此我需要添加更多的活动配置文件(可能还有一些测试属性):
有什么方法可以将其转换为基于注释的解决方案吗?我希望实现的是一组简单的注释:
@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的模拟支持。您可以跟进进度。感谢您提供的替代方案-我非常喜欢它。不过,我对这个解决方案有两个顾虑,其中一个我发现存在阻碍:我在应用程序中使用@ComponentScan(通过@SpringBootApplication),因此第二个测试类仍然可以看到并使用第一个测试静态类配置(以及所有相关的模拟内容)在TestClockRegistrar之前找不到运行此类的方法。恐怕我对如何在1.3中解决这个问题没有太多想法。希望1.4将提供更多选项供您使用。可能最简单的解决方案是加载不进行组件扫描的不同测试配置。对于静态块,您可以尝试class.forName(“”)来触发加载。谢谢Phil!我成功地克服了这个问题,但使用了一个丑陋的解决方案(将测试内容保留在生产代码中)对于测试配置有单独的元注释,并将其排除在应用程序
@ComponentScan
中。因此,我最终坚持使用概要文件。您能提供更好的模拟支持的任何ETA吗?1.4.0.M2是否仍然代表它?是的,它目前计划用于M2。仅供参考,我用Spring Boot 1.4测试增强完成了我的任务这是我旅程的简短总结:)
@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(...)
}
}
}