Spring boot test: context loaded for every test?

Perimosh picture Perimosh · Feb 22, 2018 · Viewed 19.5k times · Source

In my project we have a super class for all our tests. This is the signature of that 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 {

Where Application.class is our main class, and SomeConfiguration.class it just for some @Bean and other stuff, nothing fancy.

I use gradle, and for running my tests I do:

./gradlew :my-project:test

My problems are:

  • I'm not sure if for each test the context is being initialized. But I can assure the context gets initialized multiple times. I know this by looking at the logs.
  • Since multiple contexts are initialized, it seems that contexts overlap with each other. I know this because one of the symptoms is this exception:

    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
    
  • Even if I don't care about the multiple contexts being loaded, is my impression that when a test finishes, the next test gets a new context BEFORE the previous one is terminated. I said this because of the overlapping of the exception from above.

Since all the tests share the same JVM, when some beans get registered twice, that exception rises up. From this link:

Context caching

It is said that:

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

I understand that, but, I'm wondering how can I achieve that? My goal is to run all my tests over the same JVM and reuse the context with every test.

EDIT on Thu Feb 22

Things I tried:

  • spring.jmx.enabled: false
  • spring.jmx.default-domain: some-value

Really disabling JMX shouldn't help since the excpetion is around the EnvironmentManager, which is from Spring Cloud.

Answer

Perimosh picture Perimosh · Feb 22, 2018

I found the answer to my problem. Here is well explained:

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

Basically, if you run a bunch of tests, as soon as one of them gets started, if it uses the annotation @MockBean it will force Spring to reload the context.

Bonus: you will see the same behavior if your test uses org.mockito.Mock.