我使用
@SpringBootTest
进行了多次集成测试。
在某些情况下,Spring Boot 通过执行这些集成测试来启动多个应用程序上下文(例如,由于在特定测试类上使用 @MockBean
和 @SpyBean
,而不是在公共抽象类上定义它们),这会导致构建时间增加或更糟糕的是 - 可能会导致 Surefire 插件执行崩溃(就像我的情况一样)。
在识别并修复所有这些情况后,现在我只有两个启动的应用程序上下文(第一个没有任何模拟 bean,第二个带有模拟和间谍 bean)。
我想断言,确实在运行所有测试之后,已启动的应用程序上下文的总数尚未达到某个阈值(例如,数量不超过两个应用程序上下文)。如何实现这一目标?我发现有
DefaultContextCache
可以处理创建的应用程序上下文,但不清楚如何实现它。我们可以通过此类打开日志记录 (logging.level.org.springframework.test.context.cache: debug
),它将记录以下消息:
Spring test ApplicationContext cache statistics: [DefaultContextCache@44351c52 size = 8, maxSize = 32, parentContextCount = 0, hitCount = 2156, missCount = 8]
在此示例中
size = 8
- 显示缓存的应用程序上下文的数量(在本例中,它是应用程序上下文的总数,并且达到最大大小时不会被驱逐)。对于所描述的场景来说,这是有用的日志,但我希望进行测试来做出预期的断言,以防止将来错误地添加新的应用程序上下文。
我们可以定义自定义
TestExecutionListener
,将其注册为 TestExecutionListeners
的一部分,并使用 JUnit5 中的 @AfterAll
声明测试。
TestExecutionListener
具有接受 beforeTestClass
的方法 afterTestClass
和 TestContext
,并且它引用了 ApplicationContext
。
public class ApplicationContextAwareTestExecutionListener extends AbstractTestExecutionListener {
private static final Set<ApplicationContext> applicationContexts = new HashSet<>();
@Override
public void beforeTestClass(TestContext testContext) {
ApplicationContext applicationContext = testContext.getApplicationContext();
applicationContexts.add(applicationContext);
}
public static int getApplicationContextsCounter() {
return applicationContexts.size();
}
}
并添加测试
assertTotalNumberOfCreatedApplicationContexts
来断言:
@SpringBootTest
@TestExecutionListeners(
listeners = ApplicationContextAwareTestExecutionListener.class,
mergeMode = MergeMode.MERGE_WITH_DEFAULTS
)
public abstract class IntegrationTest {
private static final int MAX_ALLOWED_TEST_APPLICATION_CONTEXTS = 2;
@AfterAll
public static void assertTotalNumberOfCreatedApplicationContexts() {
int applicationContextsCounter = ApplicationContextAwareTestExecutionListener.getApplicationContextsCounter();
log.info("total number of created application contexts: {}", applicationContextsCounter);
assertThat(applicationContextsCounter)
.isLessThanOrEqualTo(MAX_ALLOWED_TEST_APPLICATION_CONTEXTS);
}
}