How to test multiple Spring Boot applications in one test?

Kristo Aun picture Kristo Aun · Dec 31, 2015 · Viewed 7.8k times · Source

I have a multi-module Maven project with 2 Spring Boot applications

parent

  • fooApp
  • barApp
  • test

How to set up a test where you can load separate spring boot applications, each with its own configuration context, in the same process.

public abstract class AbstractIntegrationTest {//test module

    protected FOO foo;
    protected BAR bar;

    @RunWith(SpringJUnit4ClassRunner.class)
    @WebAppConfiguration
    @IntegrationTest
    @Transactional
    @SpringApplicationConfiguration(classes = foo.Application.class)
    public class FOO {
        public MockMvc mockMvc;

        @Autowired
        public WebApplicationContext wac;

        @Before
        public void _0_setup() {
            MockitoAnnotations.initMocks(this);
            mockMvc = MockMvcBuilders.webAppContextSetup(wac).build();
            TestCase.assertNotNull(mockMvc);
        }

        public void login(String username) {
        }
    }

    @RunWith(SpringJUnit4ClassRunner.class)
    @WebAppConfiguration
    @IntegrationTest
    @Transactional
    @SpringApplicationConfiguration(classes = bar.Application.class)
    public class BAR {

        @Autowired
        public WebApplicationContext wac;

        public MockMvc restMvc;

        @Before
        public void _0_setup() {
            MockitoAnnotations.initMocks(this);
            restMvc = MockMvcBuilders.webAppContextSetup(wac).build();
            TestCase.assertNotNull(restMvc);
        }

        public void login(String username) {
        }
    }

    @Before
    public void _0_setup() {
        foo = new FOO();
        bar = new BAR();
    }
}

And an example of an integration test

public class IntegrationTest extends AbstractIntegrationTest {

    @Test
    public void login() {
        foo.login("foologin");
        bar.login("barlogin");
    }

}

Answer

rainerhahnekamp picture rainerhahnekamp · Jan 11, 2016

Given two packages com.foo.module1, and com.foo.module2 you have to create a Configuration class per package. For example for module1:

@SpringBootApplication public class Config1 {}

If you want to run the application by using only Spring beans of a single package you can do that by using the SpringApplicationBuilder. A working snippet:

   new SpringApplicationBuilder(com.foo.module1.Config1.class)
     .showBanner(false)
     .run()

That would boot up Spring with Config1, which only searches (@ComponentScan is included in @SpringBootApplication) in its package for beans.

If you have want to run the complete application, e.g. all two modules at once, you'de have to create a configuration class in the upper packages com.foo.

In the case that was mentioned below, where running the two modules within a single application might probably interfere with each other in an undesired way due to libraries like the spring-boot-starters, I can only think of two possibilities:

  1. Using OSGi: Which might not solve the issue completely and might turn out be quite a complex setup or
  2. Splitting the application into two applications and creating interfaces. Spring Boot is also a good choice for a Microservice architecture.