0
votes

We have 2 spring boot integration tests runnig on Netty.

We use gradle to run tests parallelly using flag: org.gradle.parallel=true

Test 1: @SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT) creates org.springframework.boot.web.reactive.context.AnnotationConfigReactiveWebServerApplicationContext@3736a122

Test 2: @SpringBootTest(webEnvironment = WebEnvironment.MOCK) creates org.springframework.boot.web.reactive.context.GenericReactiveWebApplicationContext@45fa13a7

Two application contexts are created and one of the application contexts randomly is injected to production code and as a result we have two sets of beans.

The following dependencies are used:

dependencySet(group: 'org.springframework', version: '5.3.5')

dependencySet(group: 'org.springframework.boot', version: '2.4.4')

Is is ok behaviour, because in one case: mock web environment is used and in another real web environment?

1
As expected as they have 2 different configs, thus 2 instances . If you are using a classic singleton to hold your ApplicationContext you will run into issues. While the tests run in parallel they run in the same JVM and thus only 1 value for the static field can exist and basically the last one started will win. To fix don't use a class like that. - M. Deinum
We don't have any static fields or do you mean singelton injection? And when we change mock to webEnvironment = WebEnvironment.RANDOM_PORT one application context is created and used everywhere. - user657009
Correct as it is the same config. No I mean static fields. But I suspect you have something like an ApplicationContextHolder in your code. At least judging from your description, else your question/problem isn't clear. Is it correct that there are 2 contexts created yes it. - M. Deinum
@Inject private ApplicationContext applicationContext; - user657009
I still don't get your question. Is this a problem? Isn't it? Is your question about the 2 contexts? Or... So again yes you have 2 contexts, and thus 2 sets of all your beans, that is to be expected. - M. Deinum

1 Answers

1
votes

When utilizing the Spring Test Context Framework it will do context caching. When the same context configuration is used it will re-use an existing context (or start one if not already there). If there is a new configuration combination (in your case there is a difference in the runtime i.e. start a real server or use a mock environment) it will start a new one.

From the aforementioned reference guide:

An ApplicationContext can be uniquely identified by the combination of configuration parameters that are 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:

  • locations (from @ContextConfiguration)
  • classes (from @ContextConfiguration)
  • contextInitializerClasses (from @ContextConfiguration)
  • contextCustomizers (from ContextCustomizerFactory) – this includes @DynamicPropertySource methods as well as various features from Spring Boot’s testing support such as @MockBean and @SpyBean.
  • contextLoader (from @ContextConfiguration)
  • parent (from @ContextHierarchy)
  • activeProfiles (from @ActiveProfiles)
  • propertySourceLocations (from @TestPropertySource)
  • propertySourceProperties (from @TestPropertySource)
  • resourceBasePath (from @WebAppConfiguration)

In this case, due to the different runtime, there is a difference in the contextCustomizers and thus no cached context is available and a new one will be started.