春季启动测试:为每个测试加载上下文?
Posted
技术标签:
【中文标题】春季启动测试:为每个测试加载上下文?【英文标题】:Spring boot test: context loaded for every test? 【发布时间】:2018-08-02 10:21:31 【问题描述】:在我的项目中,我们有一个用于所有测试的超类。这是那个类的签名
@RunWith(SpringRunner.class)
@SpringBootTest(value = "management.port=0", classes = Application.class, webEnvironment = WebEnvironment.RANDOM_PORT)
@ActiveProfiles("localhost", "test")
@ContextConfiguration(classes = Application.class, SomeConfiguration.class)
@Ignore
public abstract class AIntegrationTest
Application.class 是我们的主类,而 SomeConfiguration.class 只是用于一些 @Bean 和其他东西,没什么花哨的。
我使用 gradle,并运行我的测试:
./gradlew :my-project:test
我的问题是:
我不确定是否为每个测试初始化上下文。但我可以保证上下文被多次初始化。我通过查看日志知道这一点。由于初始化了多个上下文,因此上下文似乎相互重叠。我知道这一点是因为其中一个症状就是这个异常:
Caused by: org.springframework.jmx.export.UnableToRegisterMBeanException: Unable to register MBean [org.springframework.cloud.context.environment.EnvironmentManager@36408d9e] with key 'environmentManager'; nested exception is javax.management.InstanceAlreadyExistsException: RedeemAway:name=environmentManager,type=EnvironmentManager
即使我不关心加载的多个上下文,我的印象是,当测试完成时,下一个测试会在前一个测试终止之前获得一个新的上下文。我这么说是因为上面的异常重叠。
由于所有测试共享同一个 JVM,当某些 bean 注册两次时,就会出现该异常。从这个链接:
Context caching
据说:
ApplicationContext 可以通过以下组合来唯一标识 用于加载它的配置参数。因此, 配置参数的唯一组合用于生成 缓存上下文的键。 TestContext 框架使用 以下配置参数用于构建上下文缓存键
我明白这一点,但我想知道如何才能做到这一点?我的目标是在同一个 JVM 上运行我的所有测试,并在每个测试中重用上下文。
2 月 22 日星期四编辑
我尝试过的事情:
spring.jmx.enabled: 假 spring.jmx.default-domain: 一些值真正禁用 JMX 应该无济于事,因为异常是来自 Spring Cloud 的 EnvironmentManager。
【问题讨论】:
如果配置相同,则上下文始终在测试之间缓存。配置取决于加载的配置文件、@MockBean
(和朋友)、@TestPropertySource
和其他一些东西。如果这是您使用的,那么您每次都会获得一个新的上下文。此外,您的基类很奇怪,您要么使用 @SpringBootTest
或 @ContextConfiguration
,但不能同时使用。
SpringBootTest 文档说您可以指定 ContextConfiguration。这来自文档:“可以在运行基于 Spring Boot 的测试的测试类上指定的注释。在常规 Spring TestContext 框架之外提供以下功能:在没有特定 ContextConfiguration(loader=. ..) 已定义。不使用嵌套@Configuration 且未指定显式类时自动搜索SpringBootConfiguration。"
不,它没有这么说。尽管如此,您正在使用此复制配置。
好的。无论如何,SpringBootTest 或 ContextConfiguration 是我从昨天开始尝试的。到昨天我只有SpringBootTest,问题一模一样。
是的,你是对的。问题是我正在调试我不拥有的代码,当你提到 @MockBean 时,我的团队告诉我我们没有使用它。后来我找到了我在下面发布的链接,然后我做了一个 grep 搜索 @MockBean 并意识到我们正在使用它。删除它,一切都开始工作了。将您的评论作为答案,我会投票。毕竟,这就是答案部分的目的。
【参考方案1】:
我找到了问题的答案。这里解释得很好:
https://github.com/spring-projects/spring-boot/issues/7174
基本上,如果你运行一堆测试,一旦其中一个开始,如果它使用注解@MockBean
,它将强制 Spring 重新加载上下文。
奖励:如果您的测试使用 org.mockito.Mock
,您将看到相同的行为。
【讨论】:
在我的情况下,@Mock
没有重新加载上下文,但@MockBean
是......使用 Spring Boot 2.1.0.RELEASE。以上是关于春季启动测试:为每个测试加载上下文?的主要内容,如果未能解决你的问题,请参考以下文章
如何在@TestFactory 的每个测试中创建不同的 Spring 上下文?
spring boot单元测试spring context重复加载问题