Home > Mobile >  MockMvc with SpringBootTest is throwing exception HttpMediaTypeNotSupportedException when testing th
MockMvc with SpringBootTest is throwing exception HttpMediaTypeNotSupportedException when testing th

Time:07-06

I am testing request validation in Spring RestController with the help of integration testing and MockMvc.

ControllerTest.java

@ExtendWith(MockitoExtension.class)
@SpringBootTest(classes = Controller.class)
@AutoConfigureMockMvc(addFilters = false)
class ControllerTest {

    private ObjectMapper objectMapper;

    @MockBean
    private Service service;

    @Autowired
    private MockMvc mockMvc;

    @BeforeEach
    void setUp() {
        objectMapper = new ObjectMapper();
    }

    @Test
    void createOrAdd_shouldReturnErrorResponseOnInvalidInput() throws Exception {
        Request request = Request.builder()
                .name("name<script>")
                .primaryEmail("[email protected]")
                .build();

        mockMvc.perform(MockMvcRequestBuilders.post("/api/create")
                        .accept(MediaType.APPLICATION_JSON)
                        .contentType(MediaType.APPLICATION_JSON_VALUE)
                        .content(objectMapper.writeValueAsString(request))
                .characterEncoding("utf-8"))
                .andExpect(MockMvcResultMatchers.status().isBadRequest());
    }
}

Controller.java :

@Slf4j
@RestController
public class Controller {

    private final Service service;

    public Controller(Service service) {
        this.service = service;
    }

    @PostMapping(value = "/api/create", consumes = MediaType.APPLICATION_JSON_VALUE)
    public ResponseEntity<GenericResponse<Response>> createOrAdd(@RequestBody @Valid Request request, Errors errors) {
        GenericResponse<Response> genericResponse = new GenericResponse<>();
        try {
            if (errors.hasErrors()) {
                throw new RequestParamsException(errors.getAllErrors());
            }
            Response response = service.createOrAdd(request);
            genericResponse.setData(response);
            return ResponseEntity.ok().body(genericResponse);
        } catch (RequestParamsException ex) {
            genericResponse.setErrors(ex.getErrors());
            return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(genericResponse);
        }
    }

Error :

WARN 17304 --- [           main] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.web.HttpMediaTypeNotSupportedException: Content type 'application/json;charset=utf-8' not supported]

MockHttpServletRequest:
      HTTP Method = POST
      Request URI = /api/create
       Parameters = {}
          Headers = [Content-Type:"application/json;charset=utf-8", Accept:"application/json", Content-Length:"162"]
             Body = {"name":"name<script>alert(1)</script>","primary_email_address":"[email protected]"}
    Session Attrs = {}

Handler:
             Type = com.org.controller.Controller
           Method = com.org.controller.Controller#createOrAdd(Request, Errors)

Async:
    Async started = false
     Async result = null

Resolved Exception:
             Type = org.springframework.web.HttpMediaTypeNotSupportedException

ModelAndView:
        View name = null
             View = null
            Model = null

FlashMap:
       Attributes = null

MockHttpServletResponse:
           Status = 415
    Error message = null
          Headers = [Accept:"application/octet-stream, text/plain, application/xml, text/xml, application/x-www-form-urlencoded, application/* xml, multipart/form-data, multipart/mixed, */*"]
     Content type = null
             Body = 
    Forwarded URL = null
   Redirected URL = null
          Cookies = []

java.lang.AssertionError: Status expected:<400> but was:<415>
Expected :400
Actual   :415

I have used the correct Content-Type and Accept Headers while making a call in Test.java using mockMvc, but still it's giving HttpMediaTypeNotSupportedException. Tried many combinations in Accept and Content-Type but still not working.

I have read many SO questions related to this exception, but couldn't find what's the issue here. Still not able to figure out why it's saying HttpMediaTypeNotSupportedException.

Update : After removing addFilters = false as suggested, not able to find the handler itself.

    MockHttpServletRequest:
          HTTP Method = POST
          Request URI = /api/create
           Parameters = {}
              Headers = [Content-Type:"application/json;charset=utf-8", Accept:"application/json", Content-Length:"162"]
                 Body = {"name":"name<script>alert(1)</script>","primary_email_address":"[email protected]"}
    Session Attrs = {org.springframework.security.web.csrf.HttpSessionCsrfTokenRepository.CSRF_TOKEN=org.springframework.security.web.csrf.DefaultCsrfToken@7a687d8d}   

     
Handler:
             Type = null

Async:
    Async started = false
     Async result = null
    
    Resolved Exception:
             Type = null
    
    ModelAndView:
            View name = null
                 View = null
                Model = null
    
    FlashMap:
           Attributes = null
    
MockHttpServletResponse:
           Status = 403
    Error message = Forbidden
          Headers = [X-Content-Type-Options:"nosniff", X-XSS-Protection:"1; mode=block", Cache-Control:"no-cache, no-store, max-age=0, must-revalidate", Pragma:"no-cache", Expires:"0", X-Frame-Options:"DENY"]
     Content type = null
             Body = 
    Forwarded URL = null
   Redirected URL = null
          Cookies = []

    
java.lang.AssertionError: Status expected:<400> but was:<403>
Expected :400
Actual   :403

CodePudding user response:

I think you are missing @WebMvcTest(controllers = Controller.class)

CodePudding user response:

You need to drop the addFilters = false from your AutoConfiguration annotation

@AutoConfigureMockMvc(addFilters = false)

should just be

@AutoConfigureMockMvc

Some of those filters actually determine how to marshal the input and output of the request handlers.

If you have Security enabled, you'll want to replaces the three annotations at your class level with this:

@ExtendWith(MockitoExtension.class)
@WebMvcTest(controllers = Controller.class, excludeAutoConfiguration = SecurityAutoConfiguration.class)
@AutoConfigureMockMvc
  • Related