Test the response JSON of the REST API created in Spring MVC using AssertJ in MockMvc

Thing you want to do

When testing the REST API response created using Spring MVC's @RestController using MockMVC, use AssertJ to test the response JSON.

What is MockMVC

A mechanism for testing HTTP requests and responses to controllers without starting the server provided by Spring. Since the server is not started when the test is executed, there is an advantage that the test execution speed becomes faster. You can start the Spring application context by using @AutoConfigureMockMvc, which allows you to do DI as if you started the whole application.

Reference site: [Testing the Web Layer](Class ContentResultMatchers)

Reasons to use AssertJ

Testing with MockMVC + @ AutoConfigureMockMvc has the advantage of being able to test the entire application at high speed, I felt that the mechanism for checking the JSON returned from RestController was weak. There is also a method to compare the JSON of the response with the expected result, but you have to pass the JSON of the expected result as a string.

Reference site: Class ContentResultMatchers

For example, consider testing a RestContorller that returns a Book list like this:

Response class

Book.java



@Data
public class Book {

    private int id;
    private String name;
    private String author;
}

Books.java


@Data
@NoArgsConstructor
@AllArgsConstructor
public class Books {

    private List<Book> books;
}

Controller class

BookController


@RestController
public class BookController {

    //Service class that returns a Book list
    private final BookService bookService;

    @Autowired
    public BookController(BookService bookService) {
        this.bookService = bookService;
    }

    @GetMapping("books")
    public Books get() {

        //Get the Book list with the service and return it
        return bookService.getBooks();
    }
}

In the ContentResultMatchers class there is a public ResultMatcher json (String jsonContent) method for checking JSON It is prepared. When using this json method, pass the JSON string of the expected result as an argument. Inside the json method, after converting the passed character string to a JSON object, it is compared with the response of the program under test.

BookControllerTest



@RunWith(SpringRunner.class)
@SpringBootTest
@AutoConfigureMockMvc
public class BookControllerTest {

    @Autowired
    private MockMvc mockMvc;

    @Test
    public void test() throws Exception {

        String expectedJson = "{books:[...]}";  //Create JSON of expected result as a string

        mockMvc.perform(get("/books"))
                .andExpect(status().isOk()) //Check the status code of the response
                .andExpect(content().json(expectedJson)); //Check the JSON of the response
    }
}

I wrote a test with the json method, but I thought as follows.

-If there are many JSON items, it is difficult to create a JSON character string with the expected result. In addition, typographical errors are likely to occur because IDE completion does not work for character strings. ↓ -It seems that there are fewer mistakes if you create a Java object and convert it to a character string with Jackson. ↓ -If creating a Java object, isn't it more efficient to convert the values returned from MockMVC into Java objects and compare them? Isn't it more convenient to use AssertJ for comparison between objects because it has more matchers?

Procedure to convert the return value of MockMVC to an object and compare it with AssertJ

MockMVC provides a method that can get the response body as a character string, so use this. Convert the obtained character string to an object with Jackson and compare it with the expected result using AssertJ. The code looks like this:

BookControllerTest



@RunWith(SpringRunner.class)
@SpringBootTest
@AutoConfigureMockMvc
public class BookControllerTest {

    @Autowired
    private MockMvc mockMvc;

    @Test
    public void test() throws Exception {

        String responseJsonString = mockMvc.perform(get("/books"))
                .andExpect(status().isOk())
                .andReturn().getResponse().getContentAsString(); //Get the response body as a string

        ObjectMapper objectMapper = new ObjectMapper();

        //Convert to Java object in Jackson
        Books responseJson = objectMapper.readValue(responseJsonString, Books.class);

        //Create expected results with Java objects
        Books expected = new Books(new ArrayList<>());

        //Comparison
        assertThat(responseJson).isEqualTo(expected);

    }
}

Finally

Whether it is better to use the json method that is originally prepared depends on the content of JSON returned by the target API, and I think that there is also a preference. I hope it will be helpful to know that there is such a method.

Recommended Posts

Test the response JSON of the REST API created in Spring MVC using AssertJ in MockMvc
Json Request in Unit Test of Controller using MockMvc
Test API often used in AssertJ
Implement REST API in Spring Boot
Form that receives the value of the repeating item in Spring MVC
Settings when calling API using CSRF measures of Spring Security in JMeter
Try using the Stream API in Java
Test the integrity of the aggregation using ArchUnit ②
Try using JSON format API in Java
[Java] [Spring] Test the behavior of the logger
Test the integrity of the aggregation using ArchUnit ③
Try using JSON format API in Java
Test controller with Mock MVC in Spring Boot
ChatWork4j for using the ChatWork API in Java
The official name of Spring MVC is Spring Web MVC
Try using the COTOHA API parsing in Java
Specify the encoding of static resources in Spring Boot
[For beginners] DI ~ The basics of DI and DI in Spring ~
Get the name of the test case in the JUnit test class
I summarized the display format of the JSON response of Rails
Customize REST API error response with Spring Boot (Part 2)
Test field-injected class in Spring boot test without using Spring container
Introduce swagger-ui to REST API implemented in Spring Boot
Customize REST API error response with Spring Boot (Part 1)
Let's find out how to receive in Request Body with REST API of Spring Boot