tintin
tintin

Reputation: 5867

@ WebMvcTest loading application context

I have a GreetingController

@Controller
    public class GreetingController {
        @RequestMapping("/greeting")
        public @ResponseBody String greeting() {
            return "Hello, same to you";
        }
    }

and GreetingControllerTest

@WebMvcTest(GreetingController.class)
public class WebMockTest {

    @Autowired
    private MockMvc mockMvc;

    @Test
    public void greetingShouldReturnMessageFromService() throws Exception {
        this.mockMvc.perform(get("/greeting")).andDo(print()).andExpect(status().isOk())
                .andExpect(content().string(containsString("Hello, same to you")));
    }
}

I am running the test in intelliJ hoping that it will not load the application context, but it starts with launching the application.

 .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v2.2.5.RELEASE)

{"thread":"main","level":"INFO","loggerName":..........

As per spring doc we can narrow the tests to only the web layer by using @WebMvcTest. Does this mean that it still loads the application context? Or maybe I did not understand it correctly.

Upvotes: 2

Views: 3474

Answers (2)

Van Teo Le
Van Teo Le

Reputation: 156

I had the same problem where the test bootup the WHOLE CONTEXT(i KNOW it because it tried to load all my @Repository code), and i found a workaround for this, it's very nasty:

@ContextConfiguration(classes ={Controller.TestConfig.class})
@WebMvcTest(Controller.class)
class ControllerTest {

@Configuration
public static class TestConfig {

    @Bean
    public Controller controller() {
        return new Controller();
    }
}

I know substituting the actual Spring context with a test one is kind of a makeshift solution, but i cant think of anything else.

Upvotes: 0

rieckpil
rieckpil

Reputation: 12021

With @WebMvcTest you still get an application context, but not the full application context.

The started Spring Test Context only contains beans that are relevant for testing your Spring MVC components: @Controller, @ControllerAdvice, Converter, Filter, WebMvcConfigurer.

Injecting MockMvc using @Autowired MockMvc mockMvc; also indicates that you are working with a Spring context and the JUnit Jupiter extension (@ExtendWith(SpringExtension.class which is part of @WebMvcTest) takes care to resolve your fields by retrieving them from the Test context.

If you still don't want a Spring Test context to be started, you can write a unit test using only JUnit and Mockito. With such tests, you would only be able to verify the business logic of your controller and not things like: correct HTTP response, path variable and query parameter resolving, exception handling with different HTTP status, etc.

You can read more on the different Spring Boot Test slices here and on how to use MockMvc to test your web layer.

Upvotes: 4

Related Questions