Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Reusing a spring test context across multiple Gradle projects

I'm having a typical Gradle multi-project build:

project(':common') {
}

project(':project-a') {
    dependencies {
        compile project(':common')
        ..
    }
}

...

project(':project-n') {
    dependencies {
        compile project(':common')
        ..
    }
}

project(':app') {
    dependencies {
        compile project(':project-a')
        ..
        compile project(':project-n')

        ..
    }
}

There is a common task for all subprojects called integrataionTest that runs all integration test suites (classes). These classes inherit from a common parent annotated with the typical spring test stuff:

@ContextConfiguration // needed until Spock supports @SpringBootTest
@SpringBootTest(classes = IntegrationTestConfiguration)
@ActiveProfiles("test")
class BaseTest extends Specification {

The IntegrationTestConfiguration is @Configuration class that is annotated with @EnableAutoConfiguration and only predefines some beans other that the actual full-blown @SpringBootApplication class.

The problem is that calling gradle integrationTest seems to start a component scan, set up a Spring context, run the tests in each sub-project and then discard the context, when it's basically the same in all of them.

:app:integrationTest
[..]  INFO 38320 --- [       Thread-5] o.s.w.c.s.GenericWebApplicationContext   : Closing org.springframework.web.context.support.GenericWebApplicationContext@206e239d: startup date [..]; root of context hierarchy


:common:integrationTest
[..]  INFO 38361 --- [       Thread-5] o.s.w.c.s.GenericWebApplicationContext   : Closing org.springframework.web.context.support.GenericWebApplicationContext@a6d8c9f: startup date [..]; root of context hierarchy

:project-a:integrationTest
[..]  INFO 38362 --- [       Thread-5] o.s.w.c.s.GenericWebApplicationContext   : Closing org.springframework.web.context.support.GenericWebApplicationContext@181313ca: startup date [..]; root of context hierarchy

..

:project-n:integrationTest
[..]  INFO 38363 --- [       Thread-5] o.s.w.c.s.GenericWebApplicationContext   : Closing org.springframework.web.context.support.GenericWebApplicationContext@68ab1a32: startup date [..]; root of context hierarchy

I'm wondering if there is a way to have the whole setup being run just once and then reused in all of the different sub-projects.

like image 619
Milan Milanov Avatar asked May 23 '26 21:05

Milan Milanov


1 Answers

I don't think it's supposed to work the way you want it to - each of your sub-projects has its own testing task and its tests need to be performed in isolation from the other projects.

Also, to quote from Gradle's official documentation:

Test are always run in (one or more) separate JVMs. The sample below shows various configuration options.

This means that because your test tasks will not be sharing a JVM, they physically can not share a Spring context instance. The reason for that is the way Spring caches the test contexts. Here's a quote from the official documentation:

The Spring TestContext framework stores application contexts in a static cache. This means that the context is literally stored in a static variable. In other words, if tests execute in separate processes the static cache will be cleared between each test execution, and this will effectively disable the caching mechanism.

To benefit from the caching mechanism, all tests must run within the same process or test suite. This can be achieved by executing all tests as a group within an IDE. Similarly, when executing tests with a build framework such as Ant, Maven, or Gradle it is important to make sure that the build framework does not fork between tests. For example, if the forkMode for the Maven Surefire plug-in is set to always or pertest, the TestContext framework will not be able to cache application contexts between test classes and the build process will run significantly slower as a result.

That being said, if there's really no difference in your sub-projects' Spring configuration, you could make a new sub-project solely for integration test purposes and then perform all of your integration testing there, although if your sub-projects have no difference in Spring configuration, you could perhaps merge them or organize them differently at least.

like image 117
Miloš Milivojević Avatar answered May 27 '26 00:05

Miloš Milivojević



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!