Iscee
Iscee

Reputation: 1

415 Unsupported Media Type in MockMvc Test

I am getting a 415 error while trying to test one of my @Controller's methods. Here is my code.

Test Class:

@SpringBootTest(classes = APIController.class)
@AutoConfigureMockMvc
class APIControllerTest {

    @MockBean
    private ListifyService listifyService;

    @Autowired
    private MockMvc mvc;

    @Test
    void loginTest() throws Exception {
        when(listifyService.login(anyString(), anyString())).thenReturn("aless");

        String url = "/API/login";

        String requestJson = "{" +
                "\"email\":\"[email protected]\"," +
                "\"password\":\"password\"" +
                "}";

        mvc.perform(post(url)
                    .contentType(MediaType.APPLICATION_JSON)
                    .accept(MediaType.APPLICATION_JSON)
                    .characterEncoding("UTF-8") //if i remove this instruction, the body won't be send (empty body in test log)
                    .content(requestJson))
                    .andDo(print())
                    .andExpect(status().isOk());
    }
}

Controller Method:

@PostMapping(value="/API/login", consumes = {"application/json"}, produces = {"application/json"})
public ResponseEntity<String> login(HttpSession session, @RequestBody Map<String, String> body) {
    System.out.println("here");
    String username = listifyService.login(body.get("email"), body.get("password"));
    if (username != null) {
        session.setAttribute("username", username);
        return ResponseEntity.ok().body(username);
    } else {
        return ResponseEntity.notFound().build();
    }
}

Test Log:

MockHttpServletRequest:
      HTTP Method = POST
      Request URI = /API/login
       Parameters = {}
          Headers = [Content-Type:"application/json;charset=UTF-8", Accept:"application/json", Content-Length:"49"]
             Body = {"email":"[email protected]","password":"password"}
    Session Attrs = {}

Handler:
             Type = listify.controllers.APIController
           Method = listify.controllers.APIController#login(HttpSession, Map)

It seems strange since the controller should accept application/json mediaType, instead of returning that error.

Additionally, if I send an ajax request from javascript, it works correctly.

JS code:

response = await fetch(URL_PREFIX + "/listify/API/login", {
    method: "POST",
    headers: {
        "Content-Type": "application/json",
    },
    body: JSON.stringify({"email" : email, "password" : password}),
});

I don't know what I am doing wrong, I expect the test to be successful, since the method should return the status code 200, or, at least, accept the request and print "here".

Thanks in advance.

Upvotes: 0

Views: 40

Answers (2)

Iscee
Iscee

Reputation: 1

I found the solution of the problem: the annotation @EnableWebMvc was missing in the controller class.

I just added it and everything worked as expected.

Upvotes: 0

artiomi
artiomi

Reputation: 625

Try run test by removing APIController.class from @SpringBootTest declaration.

@SpringBootTest
@AutoConfigureMockMvc
class APIControllerTest {

    @MockBean
    private ListifyService listifyService;

    @Autowired
    private MockMvc mvc;

    @Test
    void loginTest() throws Exception {
        when(listifyService.login(anyString(), anyString())).thenReturn("aless");

        String url = "/API/login";

        String requestJson = "{" +
                "\"email\":\"[email protected]\"," +
                "\"password\":\"password\"" +
                "}";

        mvc.perform(post(url)
                    .contentType(MediaType.APPLICATION_JSON)
                    .accept(MediaType.APPLICATION_JSON)
                    .characterEncoding("UTF-8") //if i remove this instruction, the body won't be send (empty body in test log)
                    .content(requestJson))
                    .andDo(print())
                    .andExpect(status().isOk());
    }


Also instead of manually serializing request body, try to use ObjectMapper

Upvotes: 0

Related Questions