【问题标题】: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 并意识到我们正在使用它。删除它,一切都开始工作了。将您的评论作为答案,我会投票。毕竟,这就是答案部分的目的。

标签: java spring spring-boot junit spring-boot-test


【解决方案1】:

我找到了问题的答案。这里解释得很好:

https://github.com/spring-projects/spring-boot/issues/7174

基本上,如果你运行一堆测试,一旦其中一个开始,如果它使用注解@MockBean,它将强制 Spring 重新加载上下文。

奖励:如果您的测试使用 org.mockito.Mock,您将看到相同的行为。

【讨论】:

  • 在我的情况下,@Mock 没有重新加载上下文,但@MockBean 是......使用 Spring Boot 2.1.0.RELEASE。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-12-13
  • 2018-01-21
  • 1970-01-01
  • 2017-09-25
  • 1970-01-01
  • 2021-08-31
相关资源
最近更新 更多