Spring 启动测试:为每个测试加载上下文?
Spring boot test: context loaded for every test?
在我的项目中,我们为所有测试提供了超级 class。这是class
的签名
@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 是我们的主要 class,而 SomeConfiguration.class 它只是一些 @Bean 和其他东西,没什么特别的。
我使用 gradle,对于 运行我的测试我这样做:
./gradlew :my-project:test
我的问题是:
- 我不确定是否为每个测试初始化上下文。但我可以保证上下文会被多次初始化。我通过查看日志知道这一点。
由于初始化了多个context,貌似context之间有重叠。我知道这是因为其中一个症状是这个异常:
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 被注册两次时,该异常就会出现。来自这个link:
据说:
An ApplicationContext can be uniquely identified by the combination of
configuration parameters that is used to load it. Consequently, the
unique combination of configuration parameters is used to generate a
key under which the context is cached. The TestContext framework uses
the following configuration parameters to build the context cache key
我明白了,但是,我想知道我怎样才能做到这一点?我的目标是 运行 我的所有测试都在同一个 JVM 上,并在每个测试中重用上下文。
EDIT on Thu Feb 22
我尝试过的事情:
- spring.jmx.enabled: 假
- spring.jmx.default-域:一些值
真正禁用 JMX 应该没有帮助,因为异常是围绕来自 Spring Cloud 的 EnvironmentManager。
我找到了问题的答案。这里有很好的解释:
https://github.com/spring-projects/spring-boot/issues/7174
基本上,如果你 运行 一堆测试,一旦其中一个开始,如果它使用注释 @MockBean
它将强制 Spring 重新加载上下文.
奖励:如果您的测试使用 org.mockito.Mock
.
,您将看到相同的行为
在我的项目中,我们为所有测试提供了超级 class。这是class
的签名@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 是我们的主要 class,而 SomeConfiguration.class 它只是一些 @Bean 和其他东西,没什么特别的。
我使用 gradle,对于 运行我的测试我这样做:
./gradlew :my-project:test
我的问题是:
- 我不确定是否为每个测试初始化上下文。但我可以保证上下文会被多次初始化。我通过查看日志知道这一点。
由于初始化了多个context,貌似context之间有重叠。我知道这是因为其中一个症状是这个异常:
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 被注册两次时,该异常就会出现。来自这个link:
据说:
An ApplicationContext can be uniquely identified by the combination of configuration parameters that is used to load it. Consequently, the unique combination of configuration parameters is used to generate a key under which the context is cached. The TestContext framework uses the following configuration parameters to build the context cache key
我明白了,但是,我想知道我怎样才能做到这一点?我的目标是 运行 我的所有测试都在同一个 JVM 上,并在每个测试中重用上下文。
EDIT on Thu Feb 22
我尝试过的事情:
- spring.jmx.enabled: 假
- spring.jmx.default-域:一些值
真正禁用 JMX 应该没有帮助,因为异常是围绕来自 Spring Cloud 的 EnvironmentManager。
我找到了问题的答案。这里有很好的解释:
https://github.com/spring-projects/spring-boot/issues/7174
基本上,如果你 运行 一堆测试,一旦其中一个开始,如果它使用注释 @MockBean
它将强制 Spring 重新加载上下文.
奖励:如果您的测试使用 org.mockito.Mock
.