Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to test Maven module project with Spring Boot

I have split a project, based on Spring Boot, into several Maven modules. Now only the war-project contains a starter class (having a main method, starting Spring), the other modules are of type jar.

How do I test the jar projects, if they don't include a starter?

Example JUnit test case header:

@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(StarterClassInDifferentProject.class)
...
like image 392
Stefan Avatar asked Jun 03 '16 13:06

Stefan


People also ask

How do I run a Maven project in spring boot?

The Spring Boot Maven Pluginimplement a custom ClassLoader to locate and load all the external jar libraries now nested inside the package. automatically find the main() method and configure it in the manifest, so we don't have to specify the main class in our java -jar command.

What is the difference between Maven module and Maven project?

a maven module is like a maven "sub-project". a maven project includes 1 or more modules. more info here. Typically, a module generates a single artifact (jar, war, zip, etc), although this is not always true.


2 Answers

I solved a similar situation. I have a project with two modules:

  1. a "lib" project with domain and utilities classes,
  2. a "web" projects with a spring boot application, templates, controllers, etc...

and I wanted to test the "lib" project in a spring-boot-test fashion.

First, include the required dependencies with scope "test" in the pom.xml (in my case there is also the H2 database):

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <version>1.3.3.RELEASE</version>
        <scope>test</scope>
    </dependency>
    <!-- add also add this here, even if in my project it is already present as a regular dependency -->
     <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-jpa</artifactId>
        <version>1.3.3.RELEASE</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>com.h2database</groupId>
        <artifactId>h2</artifactId>
        <version>1.4.191</version>
        <scope>test</scope>
    </dependency>

For testing purposes, among the test sources of the "lib" project, I have a class that acts as my test configuration

    package my.pack.utils;

    import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
    import org.springframework.boot.autoconfigure.domain.EntityScan;
    import org.springframework.boot.test.context.TestConfiguration;
    import org.springframework.data.jpa.repository.config.EnableJpaRepositories;

    @TestConfiguration
    @EnableJpaRepositories(basePackages = {"my.pack.engine.storage", "my.pack.storage"})
    @EntityScan(basePackages = {"my.pack.storage", "my.pack.entity"})
    @EnableAutoConfiguration
    public class MyTestConfiguration
    {

    }

This sets up the H2 database in order to test the data access functionalities of the application

Finally, only in the test classes where I find it useful, I configure the execution to use the test configuration (I do not always need to do that, but sometimes it is handy):

    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration(classes = MyTestConfiguration.class)
    public class TestAClassThatNeedsSpringRepositories
    {
        // tests...
    }
like image 81
Evil Toad Avatar answered Oct 22 '22 18:10

Evil Toad


I think context tests should be available per module so you can find issues with wire and configuration early on and not depend on your full application tests to find them.

I worked around this issue with a test application class in the same module. Make sure this main class is in your test dir.

@SpringBootApplication
public class TestApplication {
    
    public static void main(String[] args) {
        SpringApplication.run(TestApplication.class, args);
    }
}

your context should work now.

@RunWith(SpringRunner.class)
@ActiveProfiles(profiles = {Profiles.WEB_REST})
@WebMvcTest(EntityController.class)
@DirtiesContext
public class ServicesControllerTest {

    @Autowired
    private MockMvc mvc;

    @MockBean
    private Controller controller;

    @Test
    public void testAll() throws Exception {
        given(controller.process(null)).willReturn(null);

        mvc.perform(get("/").accept(MediaType.APPLICATION_JSON))
                .andExpect(status().isOk());
    }
}
like image 20
Gadi Avatar answered Oct 22 '22 18:10

Gadi