Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring ApplicationContext not cached for integration testing with Maven

When integration tests start from IDE ApllicationContext loads only once and then shared between tests and it works as aspected. But executing mvn clean install new ApllicationContext created per every test. According Spring doc I've configured maven-failsafe-plugin to use single fork

<artifactId>maven-failsafe-plugin</artifactId>
 <version>2.12.4</version>
 <configuration>
    <forkCount>1</forkCount>
    <reuseForks>true</reuseForks>
...

To cache ApplicationContext used followin annotation:

@ContextConfiguration(classes = TestConfig.class)

Why context not shared when building application with maven? Actually is there is any other way speed up IT tests? Thanks.

UPDATED:

This is multimodule Maven project. Accordig Spring IT caching doc

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.

So for maven-failsafe-plugin 2.14 this config equals forkMode=once

like image 787
njjnex Avatar asked Dec 30 '15 09:12

njjnex


People also ask

How can you access the application context in a Spring integration test?

By default the ApplicationContext is loaded using the GenericXmlContextLoader which loads a context from XML Spring configuration files. You can then access beans from the ApplicationContext by annotating fields in your test class with @Autowired , @Resource , or @Inject .

How are you going to create an ApplicationContext in an integration test?

To create integration test in Spring make sure that you have Spring Test in your dependencies and, for example, JUnit. Then you need to put annotation @RunWith(SpringRunner. class) on the test class. And also add Context Configuration to your test with a list of configs in annotation @ContextConfiguration.

How can you create a shared application context in a JUnit integration test?

How can you create a shared application context in a JUnit integration test. Spring's integration testing support has the following primary goals: To manage Spring IoC container caching between tests. By default, once loaded, the configured ApplicationContext is reused for each test.

What annotation is used on an integration test method to run it in a transaction?

@Transaction annotation for integration testing in Spring Boot.


2 Answers

Few things you may want to look into:

  • version of the surefire plugin and the parallel execution configuration. According to the Surefire Fork Options - the forkCount and reuseForks are parameters for Surefire version 2.14 or later. The pom file snippet in OP states version 2.12.4
  • there seems to be something in your configuration that still causes parallel execution. In the case where 20 threads are launched, I expect that 20 application contexts are created and cached, so that all the tests executed by one thread are (re)-using the application context created for it. If that is the case, the behavior is expected in the context of multiple threads running tests - the question becomes adjusting the configuration to the number of threads desired
  • may want to experiment with various versions of Surefire, the behavior of parallel execution may differ. I've used Surefire 2.16 in other projects and without any custom configuration related to forking, all tests are executed single threaded (as the default configuration states it should)

I know this is rather a list of more things to try than a definitive answer to the OP, but I posted in the hope it might be helpful

like image 105
Xeon64 Avatar answered Oct 19 '22 05:10

Xeon64


You can try with specifiyng context location instead of classes:

@ContextConfiguration(locations = "classpath:test-context.xml")

Spring caches application contexts by locations attribute so if the same locations appears for the second time, Spring uses the same context rather than creating a new one.

It's from here: http://static.springsource.org/spring/docs/current/spring-framework-reference/html/testing.html#testing-ctx-management

Also you can read about speeding up unit tests here: http://www.nurkiewicz.com/2010/12/speeding-up-spring-integration-tests.html

UPDATE

Is your project a multi module Maven project? Accordingly to the docs:

The default setting is forkCount=1/reuseForks=true, which means that Surefire creates one new JVM process to execute all tests in one maven module.

like image 25
m.aibin Avatar answered Oct 19 '22 04:10

m.aibin