java - Spring Boot 集成测试通过注释加倍?

标签 java spring spring-boot spring-test

我正在准备一个 Spring Boot 启动器(用于测试),我希望允许最终用户通过一些测试替身轻松更改生产代码。这些应该是模块化和独立的,即:

  • 在一项 IT 中,我想模拟 Java 8 Clock @Bean,我用它来检索系统时间(通过 ZonedDateTime.now(clock)
  • 在其他模拟身份验证服务中
  • 第三个同时进行

我当前的解决方案基于具有 @Profile@Primary @BeanAutoConfiguration 类:

@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/

相关文章:

java - 即使主项目有语法错误,也可以在 android studio 中独立测试简单的 java 代码

java - 从 Hibernate persistenceContext 缓存中排除 JPA 实体?

java - 使用 Spring Boot 国际化

angular - 部署后从 URL 中删除 # 不起作用 - HTTP 404

java - 如何将 @Qualifier 与服务和存储库一起使用

java - 如何使用内存中的 H2 数据库测试 JDBI DAO?

java - 为什么 Java KeyStore 在加载 OpenPGP key 时失败?

java - 如何使用带有一些参数的 post 方法并从服务器返回成功的响应

java - 报告在后端正常,但从 spring boot 使用 ajax 下载时收到的报告为空

java - Spring boot - Thymeleaf 与 JQuery?