Search code examples
spring-bootmavenintegration-testingapplicationcontextmulti-module

Central SpringBootTest that is run in every maven-module's ApplicationContext separately


We have a modularized monolith with a maven multi-module project structure using spring-boot and doing integration-testing via @SpringBootTest which boots a module-specific Spring ApplicationContext under which the integration-tests are performed, using full DI, JPA-Connections etc.

In all those modules we use a concept of "AdminControllers" and in the central "core" module - which is depended-on and @ComponentScan by all other modules - we have a central AdminControllerIntegrationTest that asserts certain properties on all AdminController-Beans like the presence of Security-Related Annotations.

This "core" @SpringBootTest AdminControllerIntegrationTest is run once in an Application-Context specific to the core module, where it sees all core's beans - which is fine. However, in all other modules this IntegrationTest is never executed and cannot check any of their beans.

Is there any possibility to have this central @SpringBootTest be run automatically in all modules separately within their own specific ApplicationContexts?


Solution

  • Something looks wrong in this setup, let me explain:

    So you say, that you have a "core" module with its own @SpringBootTest test, which means that its a spring boot application.

    On the other hand, you say, that you have modules A and B that are spring boot applications by themselves. But if so they can't depend on another spring boot application (core), I mean spring boot application module can't depend on another spring boot application module, it doesn't make sense and doesn't work in maven.

    Another concert that comes to my mind: In any spring boot application we usually use "plug-in" like stuff: metering system, logging system, actuator and so forth. Usually for that purpose there are starters, we define those in maven and Spring boot application loads them automatically. However we treat them as "third-parties" in our application and never bother to run "their" tests while compiling our application. What you've described contradicts this approach.

    So In my understanding (and again, I might be getting it all wrong), you should:

    1. Create a starter (autoconfiguration module) out of your "core" module. It won't be a spring boot application by itself and won't have any @SpringBootTest on it. Only simple unit / integration tests (maybe driven by spring but not Spring boot in a sense of what @SpringBootTest does). You also won't have spring-boot-maven-plugin in the pom of that module and also won't have a main method in any class (no @SpringBootApplication at all).

    2. In modules A and B - plug in this autoconfiguration module, it will load automatically and will provide the required functionality. The tests of module A should test the code / flows of module A and don't need to test the functionality of the "core" module, its for "core"'s tests to check the functionality of the "core" module.

    3. In modules A and B, when you have @SpringBootTest the core module will be loaded and some of your code might break because it doesn't "match the expectations" of the core module (like you haven't placed the right annotation or something) - in this case the test will fail and you'll have to fix the code of the module A for example.

    Update 1 After reading the comments:

    I think its possible and the solution should include the following steps:

    1. Out of the module core that contains test AdminControllerIntegrationTest create an additional test jar artifact. this link contains technical instructions of what should be placed at the pom.xml of module core.

    2. Your spring boot application modules should depend on this test artifact the scope test, something like this:

    <dependency>
      <groupId>com.foo</groupId>
      <artifactId>core</artifactId>
      <version>1.0</version>
      <type>test-jar</type>
      <scope>test</scope>
    </dependency>
    
    1. From now it becomes tricky because it really depends on what exactly happens in the test and how spring plugs everything in. In the "easiest" situation, for this step you will have to make sure that your surefire/failsafe plugin is of 2.15+ version: This version adds support for dependenciesToScan option which will contain the module core so that during the build of your spring boot application the plugin will also run the AdminControllerIntegrationTest. At least it will be in the tests classpath... From there you might need to do some customizations at the level of spring, without seeing the code its hard to tell what happens. See this thread for more information