Reputation:
I have two spring boot apps one in src/test and the other in src/main. They have their separate app.properties and separate ports.
I want to make an integration test and before it runs I want it to start those two servers when I run integration test in maven. So far using pre and post maven integration test plugin has not helped and I can't seem to start both of them in Spring Boot programatically.
Also, I have realized that integration test won't connect to my main app even if I specify it with ActiveProfile and spring boot test, it just always launches my test app.
My main app:
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
@SpringBootApplication
public class App
{
public static void main( String[] args )
{
new SpringApplicationBuilder(App.class)
.build()
.run(args);
}
}
My test app:
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
@SpringBootApplication
public class MockServerApp {
public static void main(String[] args) {
// TODO Auto-generated method stub
new SpringApplicationBuilder(MockServerApp.class)
.build()
.run(args);
}
}
My integration-test
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.annotation.PropertySource;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.junit4.SpringRunner;
import com.nulogix.billing.App;
import com.nulogix.billing.mockserver.MockServerApp;
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT,classes = {App.class})
public class BillingMediatorIT {
@Test
public void testOne(){
}
}
My App.class connects to port 28433 and my MockServerApp.class connects to port 9119.
My test still connects to MockServerApp.class for some reason because it uses port 9119.
How do I fix this and make it start up the two apps pre-integration test phase.
Upvotes: 0
Views: 2520
Reputation: 42461
Some things look wrong in the question itself, I'll try to clarify
There is no point of keeping two spring boot applications: one in src/test
and one in src\main
. If you indeed need to use two different microservices - use two maven modules at least:
project
|___ app1
| |__ src/main/java - app1 production code is here
| |__ src/test/java - app1 tests are here
| |__ pom.xml
|___ app2
| |__ src/main/java - app2 production code is here
| |__ src/test/java - app2 tests are here
| |__ pom.xml
|__ pom.xml
Now Spring boot has a very good support of running one microservice with the help of @SpringBootTest
annotation that basically tries to mimic the startup of the spring boot microservice (with configuration management, component scanning and so forth) within the test. And due to spring configurations caches feature you can reuse the same application context between the test cases.
Usually integration tests in spring universe test one specific microservice with an ability to mock out some of its bean which can provide integration points to external components.
However, If you want to run 2 applications, you'll probably need a full "system test" because you test the interaction between these components. And this is kind of beyond the scope of spring itself which lives in one JVM and serves one process (application).
So, assuming, each test is done for a clean specific reason, first of all, ask yourself what exactly do you want to test?
If you want to test an internal logic of application1, for instance, maybe you should not start application 2 at all. If app1 interacts with app2 via HTTP/Rest for example, maybe you should use some kind of mock server, like wiremock or, to mock out the bean that interacts with that server in mockito, or using Internal Spring Test's Mock server that will represent a remote application like here for example
This is what works for most of the cases.
Now if you really need a system test that checks "business flows" that can involve many applications, be ready that one day you'll have to create an another application and then the test will get more complicated. Maybe you should think about creating a test environment with all the microservices and running the test suite from there. Then automate the environment creation with some script and run this script for both creating the environment and running tests on it and then removing the environments. You'll also need to care about all databases that (if) you have, configuration management, and so forth. I would suggest talking about this with Devops people at your workplace they might help you with this. You can also talk to your QA department and ask about automation of the project which can be a very interesting task, usually each company solves it in it own way.
Now how to organize code if you still need to run this from maven.
I would go with the system tests placed in a separate module (because they don't really belong neither to app1 nor to app2):
project
|___ app1
| |__ src/main/java - app1 production code is here
| |__ src/test/java - app1 tests are here
| |__ pom.xml
|___ app2
| |__ src/main/java - app2 production code is here
| |__ src/test/java - app2 tests are here
| |__ pom.xml
|__ test-module
| |__pom.xml //depends on app1, app2
| |__ src/test/java - all system tests are here
|__ pom.xml
Then make this module dependent on both app1 and app2 so that those will compile first. Then given the fact that by the time the maven builds this module the artifacts of app1 and app2 are ready.
Maven's default lifecycle has a concept of phases which are basically your hook points where you want to run plugins.
So for example, you can create a script that will run both applications (with configured ports and everything), then in pre-integration-test
phase run the script
then run all your tests as integration tests with the help of maven-failsafe-plugin
that you'll have to configure in test's module pom and then in a post-integration-test
phase run another script that will stop both applications
Upvotes: 3