在使用
@SpringBootTest
执行周期任务或具有 JMS 或 Kafka 侦听器的应用程序中使用 @Scheduled
编写集成测试时,可能会发生以下情况:
当测试 2 运行时,
@Scheduled
beans 或任何侦听器仍然处于“活动”状态。因此,并非来自“当前”应用程序上下文的侦听器可能会拾取消息或执行计划任务。这可能会导致测试不稳定。
同样,测试可能已经结束,而某些异步行为仍会在后台继续。
人们用什么来避免这种情况?
我正在考虑向此类名为
TestSuspendable
的 bean 添加一个接口,其中包含 suspend()
和 resume()
方法,通过 JUnit 5 扩展将在每次测试结束时挂起此类 bean,并在每次测试开始时恢复它们。但我不喜欢仅仅为了这样的测试而需要更改生产代码。所以我想听听是否有更好的选择。
涉及的bean(监听器容器和调度程序等)通常都实现了Spring的
Lifecycle
接口。因此,作为一个快速技巧,您可以为 BeforeAllCallback
和 AfterAllCcallback
分别为 start
和 stop
这些 bean 创建一个 JUnit5 侦听器。这应该会停止任务的监听和调度。
public class LifecycleExtension implements BeforeAllCallback, AfterAllCallback {
void beforeAll(ExtensionContext context) throws Exception {
var ctx = SpringExtension.getApplicationContext(context);
Map<String, Lifecycle> beans = ctx.getBeansOfType(Lifecycle.class);
for (var bean = beans.values()) {
if (!bean.isRunning()) {
bean.start();
}
}
}
void afterAll(ExtensionContext context) throws Exception {
var ctx = SpringExtension.getApplicationContext(context);
Map<String, Lifecycle> beans = ctx.getBeansOfType(Lifecycle.class);
for (var bean = beans.values()) {
if (bean.isRunning()) {
bean.stop();
}
}
}
}
沿着这些思路做一些事情可能会奏效。还没有测试过,只是从我的头顶输入它。但它可能为您提供了足够的信息来继续。