I have a set of integration JUnit test cases that I want to run under 2 or more separate spring application contexts. Application contexts differ in configuration settings and bean wirings. However, if I specify the application context file name using the #ContextConfiguration annotation at the top of the JUnit classes then I am only able to run these test cases once for the specified application context. Is it possible to run the same JUnit test cases with different application contexts?
Also, I am interested to execute the test cases once for each application context in the same test run - mvn test.
Put your test code in an abstract class and use subclasses with different #ContextConfigurations. See http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/testing.html#testing-examples-petclinic
You can use a master test application context file that just includes a specific context file by using Maven resource filtering
e.g.
#ContextConfiguration("classpath:test-context.xml")
where src/main/resources/test-context.xml is:
<beans>
<import resource="${project.test.context}" />
</beans>
Then run mvn test -Dproject.test.context=context1.xml, mvn test -Dproject.test.context=context2.xml etc.
If you do that, you should also set a default maven property project.test.context in your POM.
By the way, if these are integration tests, they should by convention be called ...IT.java rather than ...Test.java, and should be run by failsafe (using mvn verify), not surefire.
Related
I am building a maven project with Kotlin and Quarkus. I splitted unit and integration tests so I have a structure like :
src/
integration-test/ -> where I annotate classes with #QuarkusIntegrationTest
main/
test/ -> where I annotate classes with #QuarkusTest
I have an issue when trying to run all tests in integration-test (with mvn failsafe command, or with intelliJ). All the tests inside the first test class pass, but then the application fails to start before running tests of the second test class, stating that application port is already in use:
io.quarkus.runtime.QuarkusBindException: Port(s) already bound: 8081: Address already in use
When running each test class separately, all tests pass.
I have tried setting test-port: 0 in my application.yml, but I get the same error with the random port. Is there a way to tell quarkus to keep the same app instance for all integration test class ? Or to check that the first one has teminated completely before running the next class ? I don't know what I am doing wrong with this #QuarkusIntegrationTest annotation.
Thanks in advance for the help.
Well, this was a dumb issue; One of my test was annotated #QuarkusTest instead of #QuarkusIntegrationTest.
Say I have 10 spring boot test class (annotated with #RunWith(SpringRunner.class) and #SpringBootTest)
Each test needs to launch spring container for like 10 seconds, although the container might do the same init.
So I may need 100 seconds for "mvn test".
Is there a way I can group my 10 test class into 1 suite, and let the container only start once.
So I can:
Only run the suite for "mvn test". (with proper naming for individual test class)
Optionally run individual test in IDE.
Spring uses Cache Management to cache the Application Context between tests:
By default, once loaded, the configured ApplicationContext is reused for each test. Thus, the setup cost is incurred only once per test suite, and subsequent test execution is much faster. In this context, the term “test suite” means all tests run in the same JVM — for example, all tests run from an Ant, Maven, or Gradle build for a given project or module. In the unlikely case that a test corrupts the application context and requires reloading (for example, by modifying a bean definition or the state of an application object) the TestContext framework can be configured to reload the configuration and rebuild the application context before executing the next test. (https://docs.spring.io/spring-framework/docs/current/spring-framework-reference/testing.html#integration-testing)
So this mechanism tries to execute your integration tests on an already running Application Context if possible. As you see multiple Application Context launches, this indicates your tests somehow use a different setup e.g. different profiles active, test properties, MockBeans etc.
The Spring documentation provides an overview on which indicators it puts an Application Context in its cache: https://docs.spring.io/spring-framework/docs/current/spring-framework-reference/testing.html#testcontext-ctx-management-caching
If you e.g. don't change any test property for your integration tests, Spring can run all of them on only one Application Context and be extremely efficient.
Another indicator for your current behaviour might be the use of #DirtiesContext which leads to a fresh Application Context after your test executes.
I have a #Service class where i'm caching some table data. I don't want those queries to run while building mvn install. Is there a way to ignore the file while building and it only execute when i start the server ?
It's a spring-boot application.
Here is background of my issue. I have initialized the spring boot app from http://start.spring.io/ site, which actually adds dummy application test file with SpringBootTest annotation and default contextLoads() with Test annotation, with an intention to initialize and execute all test cases, which needs to initialize and execute all code base. In my opinion this is not required, as we can have respective Test classes per controller/manager, which will give more controlled environment to hook up your Test setups and executions.
I have removed the default application Test file and included respective test classes for code coverage and quality. This way my beans are not executed at server startup time rather build time.
Let's say we have a project that consists of some Eclipse-projects and Spring 3.1, the final result is a WAR-file. We use WTP for development. All the unit tests and integration tests are working (our Maven does this automatically). The project runs in WTP with a local configuration. In other words everything looks as if it is ready to roll.
Now we want to test run that WAR-file with different sets of configuration files for different platforms. The test should only start the context and see if that causes any issues (missing/misspelt property in a property file, too many beans for auto-wiring, ...). AFAIK it isn't necessary to have access to (or it accessible to) the outside world. Basically it should only start the context, close it and continue with the next configuration. If one context fails, the build should break.
How should we do this? Can we do this with Maven? Something external?
EDIT: Forgot to say: We will run our stuff with Tomcat 6.
Sounds like you are talking about integration test.
You should look at the failsafe plug for this:
http://maven.apache.org/surefire/maven-failsafe-plugin/usage.html
Using jetty and maven-failsafe-plugin You need to bind one of
jetty:run, jetty:run-exploded or jetty:run-war to the
pre-integration-test phase with deamon set to true, bind
failsafe:integration-test to the integration-test phase, bind
jetty:stop to the post-integration-test phase and finally bind
failsafe:verify to the verify phase. Here is an example:
Another possibility is a selenium test. Selenium tests require the war to be deployed and running before the tests are run. So there are plugins that do all this.
Then you would have a very simple selenium test case that just made a simple http request to the app to see if it was running.
You would use a different profile for each different configuration you wanted to test.
I've written some test-cases inside a single TestNG Test which extends AbstractTestNGSpringContextTests. The ApplicationContext is correctly setup and I can use it inside my test-cases.
The problem is that the setting up of the applicationContext can take some time and I don't want to do this for every test-class I have, as this would take some time which is unnecessary from my point of view.
So my question is: Is it possible to run more than one TestNG test-class using the same Spring ApplicationContext which is setup only once?
Thanks and best regards,
Robert
How about using a #BeforeSuite?
Spring may cache and re-use ApplicationContext when you use similar locations in #ContextConfiguration annotations. See related article from Tomasz Nurkiewicz (#tomasz-nurkiewicz) at http://nurkiewicz.blogspot.com/2010/12/speeding-up-spring-integration-tests.html
Once the TestContext framework loads an ApplicationContext (or WebApplicationContext) for a test, that context will be cached and reused for all subsequent tests that declare the same unique context configuration within the same test suite.
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.