MockMvc HttpMediaTypeNotSupportedException:不支持内容类型“应用程序/json”

Posted

技术标签:

【中文标题】MockMvc HttpMediaTypeNotSupportedException:不支持内容类型“应用程序/json”【英文标题】:MockMvc HttpMediaTypeNotSupportedException: Content type 'application/json' not supported 【发布时间】:2017-11-17 04:25:45 【问题描述】:

我收到以下异常:

org.springframework.web.HttpMediaTypeNotSupportedException: Content type 'application/json' not supported

    at org.springframework.web.bind.annotation.support.HandlerMethodInvoker.readWithMessageConverters(HandlerMethodInvoker.java:653)
    at org.springframework.web.bind.annotation.support.HandlerMethodInvoker.resolveRequestBody(HandlerMethodInvoker.java:612)
    at org.springframework.web.bind.annotation.support.HandlerMethodInvoker.resolveHandlerArguments(HandlerMethodInvoker.java:361)
    at org.springframework.web.bind.annotation.support.HandlerMethodInvoker.invokeHandlerMethod(HandlerMethodInvoker.java:175)
    at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.invokeHandlerMethod(AnnotationMethodHandlerAdapter.java:440)
    at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.handle(AnnotationMethodHandlerAdapter.java:428)
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:963)
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:897)
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970)
    at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:872)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:661)
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846)
    at org.springframework.test.web.servlet.TestDispatcherServlet.service(TestDispatcherServlet.java:65)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:742)
    at org.springframework.mock.web.MockFilterChain$ServletFilterProxy.doFilter(MockFilterChain.java:167)
    at org.springframework.mock.web.MockFilterChain.doFilter(MockFilterChain.java:134)

我的测试如下所示:

public class AvailabilityControllerTest extends BaseTest    
    @Test
    public void createAvailability() throws Exception 
        final String createAvailabilityEndPoint = "/api/v4/companies/123/availabilities";
        final String responseName = "availabilityResponseDTO";

        AvailabilityDTO availabilityDTO = new AvailabilityDTO();

        MvcResult mvcResult = mockMvc.perform(
                MockMvcRequestBuilders.post(createAvailabilityEndPoint)
                        .contentType(MediaType.APPLICATION_JSON_VALUE)
                        .accept(MediaType.APPLICATION_JSON_VALUE)
                        .content(new ObjectMapper().writeValueAsString(availabilityDTO)))
                .andExpect(MockMvcResultMatchers.status().isCreated())
                .andReturn();
    

BaseTest 为:

@RunWith(SpringRunner.class)
@SpringBootTest(classes = TestConfiguration.class)
@AutoConfigureMockMvc
public class BaseTest 

    @Autowired
    protected MockMvc mockMvc;


TestConfiguration 如下所示:

@Configuration
@ComponentScan(
        basePackages = "com.app",
        excludeFilters = 
                @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = App.class)
        
)
public class TestConfiguration 

    @Bean
    public ErrorAttributes errorAttributes() 
        return new DefaultErrorAttributes();
    

AvailabilityController 看起来像这样:

@RestController
@RequestMapping("/api/v4/companies")
public class AvailabilityController 

    public static final String ACCEPT_APP_JSON = "Accept=" + AcceptableMediaType.APPLICATION_JSON;

    @Autowired
    private AvailabilityFacade availabilityFacade;

@RequestMapping(value = "/companyId/employees/employeeId/availabilities", method = RequestMethod.GET)
    public List<AvailabilityEventResponseDTO> getUserAvailabilities(@PathVariable String companyId,
                                                                    @PathVariable String employeeId) 
        return availabilityFacade.getUserAvailabilities(employeeId);
    

    @RequestMapping(value = "/companyId/availabilities", method = RequestMethod.POST, headers = ACCEPT_APP_JSON, consumes = MediaType.APPLICATION_JSON_VALUE)
    public ResponseEntity<AvailabilityResponseDTO> createAvailability(@PathVariable String companyId,
                                                                      @Valid @RequestBody AvailabilityDTO availabilityDTO) 
        return new ResponseEntity<>(
                availabilityFacade.createAvailability(companyId, availabilityDTO),
                HttpStatus.CREATED
        );
    

基本上,GET 请求适用于 MockMvc,但 POST 不适用,并返回此 HttpMediaTypeNotSupportedException。我尝试在请求和控制器中添加和删除接受和内容类型的标头,但这似乎不起作用。

这个问题似乎与Spring integration test with mockmvc throws org.springframework.web.HttpMediaTypeNotSupportedException: Content type 'application/json' not supported 有关,但在这种情况下删除 TestConfiguration 中的 excludeFilters 不允许 Spring 解释上下文。另外,我不确定 Karl R 所说的“在我的类路径中包含服务器运行时”是什么意思。

感谢任何帮助。

【问题讨论】:

【参考方案1】:

在我的情况下,问题是我没有设置contentType,因此将其设置为 JSON 类型解决了我的问题。

...
.contentType(MediaType.APPLICATION_JSON)
...

【讨论】:

【参考方案2】:

我认为您应该将 @EnableWebMvc 添加到您的 TestConfiguration。

@Configuration
@ComponentScan(
     basePackages = "com.app",
    excludeFilters = 
            @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, 
              classes = App.class)
    
)
@EnableWebMvc
public class TestConfiguration 

【讨论】:

没有正确错误消息的最烦人的错误之一。谢谢!

以上是关于MockMvc HttpMediaTypeNotSupportedException:不支持内容类型“应用程序/json”的主要内容,如果未能解决你的问题,请参考以下文章

MockMvc 测试 OPTIONS 请求

Spring 的 MockMvc 是用于单元测试还是集成测试?

使用mockmvc测试如何处理无序数组

集成测试中 MockMvc 和 RestTemplate 的区别

MockMvc 测试 POST 请求

MockMVC - 如何使用 org.hamcrest.Matcher 在春季安全集成测试中检查 JWT 令牌的内容