【问题标题】:Spring boot disable @EnableAsync for integration testsSpring Boot 禁用 @EnableAsync 进行集成测试
【发布时间】:2018-05-04 19:24:30
【问题描述】:

我想在运行集成测试时禁用 @EnableAsync

我试图用我的测试包中同名的类覆盖带有 @EnableAsync 注释的配置文件,但它不起作用。

在本主题中:Is it possible to disable Spring's @Async during integration test?

我已经看到了:

您可以...创建一个测试配置或简单地使用 SyncTaskExecutor 覆盖任务执行器

但我不明白该怎么做。

有什么建议吗?谢谢

【问题讨论】:

    标签: spring-boot integration-testing spring-test-mvc


    【解决方案1】:

    您链接的主题确实提供了一个很好的解决方案。

    要为测试创建SyncTaskExecutor,请确保您实际上有一个用于spring 上下文的测试配置类。请参阅 Spring 文档: https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-testing.html

    在这个配置类中添加一个新的bean:

    @Bean
    @Primary
    public TaskExecutor taskExecutor() {
        return new SyncTaskExecutor();
    }
    

    应该这样做!

    注意不要在你的实时配置中创建这个 bean!

    【讨论】:

    • 我最后做的是在我的 AsyncConfiguration 类上添加一个@Profile("!test")。谢谢
    【解决方案2】:

    您可以通过在测试文件夹中创建以下类来覆盖主任务执行器:

    @TestConfiguration
    public class TestAsyncConfig {
        // create this bean if you have a custom executor you want to overwrite
        @Bean(name = "xxxxxxx") 
        public Executor xxxxxxx() {
            return new SyncTaskExecutor();
        }
    
        // this will overwrite the default executor
        @Bean
        public Executor taskExecutor() { 
            return new SyncTaskExecutor();
        }
    }
    

    然后将以下内容添加到集成测试的注释中:

    @ContextConfiguration(classes = TestAsyncConfig.class)
    

    【讨论】:

      【解决方案3】:

      您还可以在您的类中创建两个方法,一个在其中包含 @Async 注释,第二个将包含您需要在没有此注释的情况下测试的所有逻辑,并使第一个方法调用第二个方法.然后在您的测试中调用第二个方法,该方法将具有package-private 可见性。

      例如:

      @Async
      public void methodAsync() {
          this.method();
      }
      
      void method() {
         // Your business logic here!
      }
      

      【讨论】:

      • 你不应该仅仅为了测试而改变生产代码
      • 在我看来,您只是传递了框架工具。也可以不返回void,而是返回CompletableFuture,并在测试期间强制CompletableFuture.completedFuture() 具有适当的值。最后,您需要确保您的业务逻辑有效,而不是您使用的框架。
      【解决方案4】:

      我们最终使用了一个默认为true 的道具yourcompany.someExecutor.async(所以它确实不会显示在application.yml 中),并且在测试中我们将其设置为false使用TestPropertySource。基于该道具,我们要么初始化SyncTaskExecutor,要么初始化一些异步版本(例如ThreadPoolTaskExecutor)。

      请注意,这也可以使用多个道具,因此很容易禁用每个道具的特定执行器。在我们的例子中,我们有几个异步执行器,具体取决于上下文。

      @RunWith(SpringRunner.class)
      @SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
      @TestPropertySource(properties = {
              "yourcompany.someExecutor.async=false",
      })
      public class SomeIntegrationTest {
        // ... tests requiring async disabled
      }
      
      @Configuration
      public class SomeConfig {
          // ...
          @Value("${yourcompany.someExecutor.async:true}")
          private boolean asyncEnabled;
      
          @Bean("someExecutor") // specific executor
          public Executor algoExecutor() {
              if (!asyncEnabled) {
                  return new SyncTaskExecutor();
              }
              ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
              executor.setCorePoolSize(THREAD_COUNT);
              executor.setMaxPoolSize(THREAD_COUNT);
              executor.setQueueCapacity(QUEUE_CAPACITY);
              executor.setThreadNamePrefix("Some-");
              executor.initialize();
              return executor;
          }
      }
      

      【讨论】:

      • 生产配置不应该包含这样的逻辑
      猜你喜欢
      • 2018-02-01
      • 2020-07-24
      • 1970-01-01
      • 2014-08-15
      • 2020-04-09
      • 1970-01-01
      • 2018-07-16
      • 2020-02-25
      • 1970-01-01
      相关资源
      最近更新 更多