javaspringspring-bootspring-mvcmockmvc

spring mock mvc perform post request body is missing : error 400


I try to mock a mvc request for testing end to end my controller in spring.

The post request needs a request body but I get an error 400 telling me that required request body is missing even though I see its body using MockMvcResultsHandler print.

project architecture :

So here's my application.properties

spring.datasource.url=jdbc:h2:mem:tesdb;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.username=*****
spring.datasource.password=*****
spring.jpa.show-sql = true

Here's my test

@SpringBootTest
@AutoConfigureMockMvc
public class IntegrationTest {
    protected User mockUser;
  
    protected List<User> allUsers;

    @Autowired
    private MockMvc mvc;

    @Autowired
    private WebApplicationContext webApplicationContext;

    @BeforeEach
    public void setUp() {
        this.mvc = MockMvcBuilders.webAppContextSetup(this.webApplicationContext).build();
    }
    
    @Test
    void testGetAllUsers() throws Exception {
        this.mvc.perform(post("/api/users")
        .accept(MediaType.APPLICATION_JSON)
        .contentType(MediaType.APPLICATION_JSON)
        .characterEncoding("utf-8")     
        .content("{\"name\":\"name\"}"))
        .andDo(print())
        .andExpect(status().isCreated());
   }
}

My @RestController

    @PostMapping(path = "/users")
    public @ResponseBody ResponseEntity<User> addNewUser(
        @RequestBody String name        
    ) {
        return userService.createUser(name);
    }

and my user @Service

public ResponseEntity<User> createUser(String name) {
        User user = new User();
        user.setName(name);
        userRepository.save(user);

And when I try to launch my test I get in my debug console

DefaultHandlerExceptionResolver : Resolved [org.springframework.http.converter.HttpMessageNotReadableException: Required request body is missing: public org.springframework.http.ResponseEntity<java.lang.String> ....addNewType(java.lang.String,java.lang.Boolean)]

MockHttpServletRequest:
      HTTP Method = POST
      Request URI = /api/users
       Parameters = {}
          Headers = [Content-Type:"application/json;charset=utf-8", Accept:"application/json", Content-Length:"32"]
             Body = {"name":"concat"}
    Session Attrs = {}

and response is :

MockHttpServletResponse:
           Status = 400
    Error message = null
          Headers = []
     Content type = null
             Body = 
    Forwarded URL = null
   Redirected URL = null
          Cookies = []

get methods seems to work when I use the same architecture, body seems to be present in the console but servelt doesn't seem to see/understand the request body.


Solution

  • So this was a simplified example of my real web service. Problem came from the fact that I used several time @RequestBody in the same request

    public @ResponseBody ResponseEntity<User> addNewUser(
            @RequestBody String name ,
            @RequestBody String lastName,
    

    which was the source of the problem.

    To solve that I created a DTO like

    public @ResponseBody ResponseEntity<User> addNewUser(
            @RequestBody UserDTO userDto
    

    And now it is working fine