20
votes

I created multiple spring-boot testing class, (with spring-boot 1.4.0).

FirstActionTest.java:

@RunWith(SpringRunner.class)
@WebMvcTest(FirstAction.class)
@TestPropertySource("classpath:test-application.properties")
public class FirstActionTest {
    @Autowired
    private MockMvc mvc;

    // ...
}

SecondActionTest.java:

@RunWith(SpringRunner.class)
@WebMvcTest(SecondAction.class)
@TestPropertySource("classpath:test-application.properties")
public class SecondActionTest {
    @Autowired
    private MockMvc mvc;

    // ...
}

When run test via:

mvn test

It seems created a spring test context for each testing class, which is not necessary I guess.

The question is:

  • Is it possible to share a single spring test context among multiple testing class, and if yes, how?
1
@kuhajeyan The link is for xml based configuration, even in spring2.5 we can do that quite easily. But with spring-boot, usually there is no configuration file for context, not sure how to adapt that into spring-boot. - user218867
Saw on their documentation that it caches the context but not working for me, it reloads for every test class. > Spring’s test framework will cache application contexts between tests. Therefore, as long as your tests share the same configuration (no matter how it’s discovered), the potentially time consuming process of loading the context will only happen once. docs.spring.io/spring-boot/docs/current/reference/html/… - Ahmed

1 Answers

13
votes

By using two different classes with @WebMvcTest (i.e @WebMvcTest(FirstAction.class) and @WebMvcTest(SecondAction.class)) you are specifically indicating that you want different application contexts. You can't share a single context in this case because each context contains a different set of beans. If you're controller beans are fairly well behaved then the context should be relatively quick to create and you shouldn't really have a problem.

If you really want to have a context that can be cached and shared across all web tests, then you need to ensure that it contains exactly the same bean definitions. Two options that spring to mind:

1) Use @WebMvcTest without any controller specified.

FirstActionTest:

@RunWith(SpringRunner.class)
@WebMvcTest
@TestPropertySource("classpath:test-application.properties")
public class FirstActionTest {
    @Autowired
    private MockMvc mvc;

    // ...
}

SecondActionTest:

@RunWith(SpringRunner.class)
@WebMvcTest
@TestPropertySource("classpath:test-application.properties")
public class SecondActionTest {
    @Autowired
    private MockMvc mvc;

    // ...
}

2) Don't use @WebMvcTest at all so you get an application context that contains all beans (not just web concerns)

FirstActionTest:

@RunWith(SpringRunner.class)
@SpringBootTest
@TestPropertySource("classpath:test-application.properties")
public class FirstActionTest {
    @Autowired
    private MockMvc mvc; // use MockMvcBuilders.webAppContextSetup to create mvc

    // ...
}

SecondActionTest:

@RunWith(SpringRunner.class)
@SpringBootTest
@TestPropertySource("classpath:test-application.properties")
public class SecondActionTest {
    @Autowired
    private MockMvc mvc; // use MockMvcBuilders.webAppContextSetup to create mvc

    // ...
}

Keep in mind that a cached context can make running multiple tests faster, but if you're repeatedly running a single test at development time, you're paying the cost of creating a lot of beans that then immediately get thrown away.