【问题标题】:Customize Test Application Context自定义测试应用程序上下文
【发布时间】:2021-07-28 20:28:02
【问题描述】:

我一直在拼命地尝试构建一个需要来自 JUnit5 扩展模型和 Spring-Boot 测试框架的信息的扩展。具体来说,我想使用 ApplicationContextInitializer 和自定义注释来挂钩 ApplicationContext 创建过程:

@Retention(RUNTIME)
@Target(TYPE)
@ContextConfiguration(initializers = CustomContextInitializer.class)
public @interface CustomAnnotation {
    String someOption();
}

然后测试看起来像这样:

@SpringBootTest
@CustomAnnotation(someOption = "Hello There")
public class SomeTest {
    ...
}

现在,如何从我的CustomContextInitializer 中访问测试类的CustomAnnotation 实例?

class CustomContextInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {

    @Override
    public void initialize(ConfigurableApplicationContext applicationContext) {

        // How to access the Test Class here?

        CustomAnnotation annotation = <Test Class>.getAnnotation(CustomAnnotation.class);
        System.out.println(annotation.someOption());
    }
}

是否有可能在创建 ApplicationContext 期间以某种方式访问​​ JUnit5 ExtensionContext?它不必来自ApplicationContextInitializer。我只需要一个足够早执行的钩子,这样我就可以在整个 bean 实例化过程实际开始之前注入一些动态生成的属性。

【问题讨论】:

    标签: java junit5 spring-test spring-boot-test


    【解决方案1】:

    您可以实现自己的TestExecutionListener 并使用它来访问您提到的注释

    @Retention(RUNTIME)
    @Target(ElementType.TYPE)
    @TestExecutionListeners(listeners = CustomTestExecutionListener.class, mergeMode = TestExecutionListeners.MergeMode.MERGE_WITH_DEFAULTS)
    @interface CustomAnnotation {
        String someOption();
    }
    
    static class CustomTestExecutionListener implements TestExecutionListener {
        @Override
        public void beforeTestClass(TestContext testContext) throws Exception {
           final CustomAnnotation annotation = testContext.getTestClass().getAnnotation(CustomAnnotation.class);
           System.out.println(annotation.someOption());
        }
    }
    
    

    【讨论】:

      【解决方案2】:

      查看@DynamicPropertySource 在 bean 初始化之前注入属性。然后,您可以使用@RegisterExtension 注册一个自定义扩展,该扩展读取注释属性并通过某种方法使它们可用:

      @CustomAnnotation(someOption = "Hello There")
      public class SomeTest {
          @RegisterExtension
          static CustomExtension extension = new CustomExtension();
      
          @DynamicPropertySource
          static void registerProperties(DynamicPropertyRegistry registry) {
              registry.add("property.you.need", 
                () -> customExtension.getProperty());
          }
      }
      
      public class CustomExtension implements BeforeAllCallback {
          private String property;
      
          public String getProperty() {
              return property;
          }
      
          @Override
          public void beforeAll(ExtensionContext context) throws Exception {
              CustomAnnotation annotation = context.getRequiredTestClass()
                  .getAnnotation(CustomAnnotation.class);
              property = annotation.someOption();
          }
      }
      

      我知道它不能回答有关使用 Spring 初始化机制挂钩 JUnit 5 的问题,但如果您只需要动态属性,这正好解决了这个问题。

      【讨论】:

      • 问题是,我想使用注解的属性来生成我的自定义属性,所以我需要访问注解实例
      • 我可能错了,但据我所知,没有简单的方法可以做到这一点。我已经改变了我的答案以反映这一点。可以使用@RegisterExtension 注册一个读取注解属性的自定义扩展。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-03-04
      • 2015-05-21
      • 1970-01-01
      • 2011-11-03
      相关资源
      最近更新 更多