我想在运行集成测试时禁用@EnableAsync
。
我尝试通过创建与我的测试包中同名的类来覆盖带有@EnableAsync
注释的配置文件,但它不起作用。
在此主题中:是否可以在集成测试期间禁用Spring的@Async?
我看到:
您可以... 创建一个测试配置或仅使用SyncTaskExecutor覆盖任务执行程序
但我不明白如何操作。
有什么建议吗?谢谢
我想在运行集成测试时禁用@EnableAsync
。
我尝试通过创建与我的测试包中同名的类来覆盖带有@EnableAsync
注释的配置文件,但它不起作用。
在此主题中:是否可以在集成测试期间禁用Spring的@Async?
我看到:
您可以... 创建一个测试配置或仅使用SyncTaskExecutor覆盖任务执行程序
但我不明白如何操作。
有什么建议吗?谢谢
您提供的链接主题确实提供了一个好的解决方案。
要为测试创建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!
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import org.springframework.scheduling.annotation.EnableAsync;
@Profile("!test")
@Configuration
@EnableAsync
public class AsyncConfiguration {
}
src/test/resources/application.yml
中,以确保测试在名为“test”的配置文件下运行。spring:
profiles:
active: test
您可以通过在测试文件夹中创建以下类来覆盖主任务执行器:
@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)
@Configuration
@Profile("disable-async")
public class DisableAsyncConfiguration {
@Bean
Executor asyncExecutor() {
return new SyncTaskExecutor();
}
}
@SpringBootTest
@@ActiveProfiles(profiles = {"test", "disable-async"})
public class MyTestThatUsesAsyncAnnotatedBeans {
...
}
yourcompany.someExecutor.async
的属性,我们将其默认设置为 true
(因此它不会出现在 application.yml
中),并且在测试中,我们使用 TestPropertySource
将其设置为 false
。基于该属性,我们要么初始化一个 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;
}
}
@Async
注释,另一个将拥有所有需要测试的逻辑但不包含此注释,并使第一个方法调用第二个方法。然后在你的测试中,你调用具有package-private
可见性的第二个方法。@Async
public void methodAsync() {
this.method();
}
void method() {
// Your business logic here!
}
CompletableFuture
而不是 void,并在测试期间强制使用带有适当值的 CompletableFuture.completedFuture()
。最终,你需要确保你的业务逻辑正常运行,而不是你正在使用的框架。 - Felipe Moraes
@Profile("!test")"
гҖӮи°ўи°ўгҖӮ - psv@SpringBootTest
和@Transactional
,并在后台进行一些@Async
操作,但由于线程绑定事务,我的@BeforeEach
方法没有意识到数据库设置的问题。唉! - andy