Using this annotation will disable full auto-configuration and instead apply only configuration relevant to MVC tests (i.e. @Controller
, @ControllerAdvice
, @JsonComponent
, Converter/GenericConverter, Filter
, WebMvcConfigurer
and HandlerMethodArgumentResolver
beans but not @Component
, @Service
or @Repository
beans
Testing web layer in Spring Boot using WebMvcTest
Upasana | November 26, 2019 | 2 min read | 568 views
In this tutorial we will write a Spring Boot based test class that tests the web layer of our application without loading the full Spring context. These tests are often used to verify single or multiple containers
Perquisites
-
Java 8 or Java 11
-
Gradle 5+
-
Spring boot 2.2.1
-
Junit 5
Using @SpringBootTest
in tests will load the full Spring application context but without the server. But we can narrow down the testing scope to just web layer by using @WebMvcTest
annotation.
Using @WebMvcTest
, Spring Boot will only instantiate the web layer, not the whole context. That means:
We can ask for just one controller to be initialized using @WebMvcTest(GreetingController.class)
Let’s create a simple Spring Boot application with a controller and service layer
We can use https://start.spring.io to create a sample application.
We are using gradle build system to manage the build dependencies.
plugins {
id 'org.springframework.boot' version '2.2.1.RELEASE'
id 'java'
}
apply plugin: 'io.spring.dependency-management'
group = 'com.shunya.tutorial'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '11'
repositories {
mavenCentral()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
}
We will create a simple controller that has a /greeting
endpoint, which invokes a service to capture the greeting response.
@Controller
public class GreetingController {
private final GreetingService service;
public GreetingController(GreetingService service) {
this.service = service;
}
@RequestMapping("/greeting")
@ResponseBody
public String greeting() {
return service.greet();
}
}
Here is our dummy GreetingService
which just returns a mocked response.
@Service
public class GreetingService {
public String greet() {
return "Hello World";
}
}
Now lets write a simple class that will do the web layer testing for us:
import org.junit.jupiter.api.Test;
import org.springframework.test.web.servlet.MockMvc;
import static org.hamcrest.Matchers.containsString;
import static org.mockito.Mockito.when;
import static org.springframework.test.*;
@WebMvcTest(GreetingController.class)
public class WebMockTest {
@Autowired
private MockMvc mockMvc;
@MockBean
private GreetingService service;
@Test
public void greetingShouldReturnMessageFromService() throws Exception {
when(service.greet()).thenReturn("Hello Mock");
this.mockMvc
.perform(get("/greeting"))
.andDo(print())
.andExpect(status().isOk())
.andExpect(content().string(containsString("Hello Mock")));
}
}
The above test will instantiate GreetingController
but not the GreetingService
component.
We can see that WebMvcTest
is often used along with @MockBean
to create any collaborators required by our @Controller beans.
Top articles in this category:
- Spring Boot 2.0 Reactive Web Performance Metrics
- Slack Webhook Message from Spring Boot
- Feign RequestInterceptor in Spring Boot
- Sendgrid Dynamic Templates with Spring Boot
- Basic Auth Security in Spring Boot 2
- Redis rate limiter in Spring Boot
- SendGrid emails in Spring Boot