Integration Testing with Spring Boot
Integration Testing with Spring Boot
Now that I have implemented a part of the API across all 3 layers, it’s time to write an integration test.
For the integration test, I want to send a get request to the API and it should go through all three layers and come back with a response, and this response will be asserted according to the expectations of the API.
Two approaches to Integration testing with Spring
- Start a server and send the request using the
TestRestTemplate
, provided by Spring.
- Use
MockMVC
to handle the HTTP request and pass it on to the Controller, the code will be executed exactly the same way as if it was processing a real HTTP request, but without the cost of having to start a server.
So I’m going to use the second approach in my integration tests. For this, I need the support of the MockMvc
class.
Using the MockMvc
I can perform
GET, POST, AND DELETE operations.
The perform
method will return a result as a ResultAction
on which I can perform operations such as andDo
, andReturn
and andExpect
.
Spring Boot testing annotations
The Test class should be annotated with the following annotations.
Example
@RunWith(SpringRunner.class)
@SpringBootTest
@AutoConfigureMockMvc
public class CommentApiTest {
}
Let’s see why we need them.
@RunWith(SpringRunner.class)
This will bring Spring’s testing support to our JUnit test, such as loading the application context and auto wiring the beans.
This annotation is not required when using JUnit5
@SpringBootTest
This annotation tells the SpringRunner
to start the application as a Spring Boot application.
By default, it does not start a server, instead, it loads a web ApplicationContext and provides a mock web environment. You can use the webEnvironment attribute if you want to set other options such as RANDOM_PORT
, DEFINED_PORT
, or NONE
.
Read more at https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#boot-features-testing-spring-boot-applications
Difference between @SpringBootTest and @WebMvcTest
@SpringBootTest
will load the complete application and autowire all the beans, which makes it a bit slow.
Use @WebMvcTest
if you only want to test the Controller layer and happy to mock all other dependencies, tests will run much faster.
@AutoConfigureMockMvc
This annotation auto-configures the MockMvc
.
Spring Boot MockMvc Example
Following is the source code example of a very simple test using MockMvc
.
package com.comment;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
import static org.hamcrest.Matchers.*;
import javax.inject.Inject;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.MediaType;
import org.springframework.test.context.jdbc.Sql;
import org.springframework.test.context.jdbc.Sql.ExecutionPhase;
import org.springframework.test.context.jdbc.SqlGroup;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;
@RunWith(SpringRunner.class)
@SpringBootTest
@AutoConfigureMockMvc
public class CommentApiTest {
@Inject
private MockMvc mvc;
@Before
public void setUp() throws Exception {
}
@Test
public void testCommentApiGetCommentsByPostId_statusOk() throws Exception {
mvc.perform(get("/posts/1/comments")).andExpect(status().isOk());
}
}