You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring MockMVC测试POST请求时出现415媒体类型不支持错误

问题描述

我有一个用于创建实体的REST POST接口,使用MockMVC测试时,每次请求都返回415状态码(媒体类型不支持),错误信息如下:

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

接口接收JSON格式请求体,MockMVC中已设置contentType为APPLICATION_JSON_VALUE,并通过Jackson序列化对象作为请求内容。

控制器受Spring Security过滤器管理,但已使用@AutoConfigureMockMvc(addFilters = false),且415是媒体类型问题,排除安全相关原因。

尝试过在控制器或测试配置类添加@EnableWebMvc,也试过切换MediaType.APPLICATION_JSON和MediaType.APPLICATION_JSON_VALUE,均无效。

相关代码如下:

测试配置类

@TestConfiguration
@EnableWebMvc
public class ProdutoControllerConfigurationTest {
    @Bean
    public ProdutoController produtoController() {
        return new ProdutoController(/* dependencies by autowired */);
    }
}

DTO类

public class CriarProdutoDTO {
    @NotNull
    @Size(min = 2)
    @JsonProperty("nome_produto")
    private final String nomeProduto;

    @DecimalMin("0.1")
    private final BigDecimal preco;
    private final String descricao;

    @NotNull
    @Min(0)
    @JsonProperty("quantidade_estoque")
    private final Integer quantidadeEstoque;

    @NotNull
    @Min(1)
    @JsonProperty("categoria_id")
    private final Integer categoriaId;

    public CriarProdutoDTO(String nomeProduto, BigDecimal preco, String descricao, Integer quantidadeEstoque, Integer categoriaId) {
        this.nomeProduto = nomeProduto;
        this.preco = preco;
        this.descricao = descricao;
        this.quantidadeEstoque = quantidadeEstoque;
        this.categoriaId = categoriaId;
    }
}

测试代码

@ActiveProfiles("testes")
@ExtendWith(SpringExtension.class)
@SpringBootTest
@WebAppConfiguration
@AutoConfigureMockMvc(addFilters = false)
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.ANY)
public class ProdutoControllerTest {

    @Autowired
    private MockMvc mockMvc;
    @Autowired
    private ObjectMapper objectMapper;

    @Test
    public void deveRetornarCreated_criacaoProdutoSucesso() throws Exception {
        CriarProdutoDTO criarProdutoDTO = new CriarProdutoDTO("Nome", new BigDecimal("2.0"), "DESCRIÇÃO", 2, 1);

        mockMvc.perform(MockMvcRequestBuilders.post("/api/produtos")
                .contentType(MediaType.APPLICATION_JSON_VALUE)
                .content(objectMapper.writeValueAsString(criarProdutoDTO)))
                .andDo(MockMvcResultHandlers.print())
                .andExpect(MockMvcResultMatchers.status().isCreated());
    }

}

控制器代码

@RestController
@RequestMapping(value = "/api/produtos")
public class ProdutoController {

    @Autowired
    private ProdutoService produtoService;
    @Autowired
    private CriarProdutoDtoToProdutoConverter produtoConverter;

    @PostMapping
    @ResponseStatus(HttpStatus.CREATED)
    public void cadastrar(@RequestBody @Valid CriarProdutoDTO produtoDTO) {
        Produto novoProduto = produtoConverter.converter(produtoDTO);
        produtoService.cadastrar(novoProduto);
    }
}
解决方案

针对415媒体类型不支持的问题,可按以下步骤排查修复:

  • 修复DTO的Jackson反序列化支持:
    你的CriarProdutoDTO只有全参构造器,Jackson默认需要无参构造器或配合@ConstructorProperties注解完成JSON反序列化。可以给全参构造器添加注解:

    @ConstructorProperties({"nomeProduto", "preco", "descricao", "quantidadeEstoque", "categoriaId"})
    public CriarProdutoDTO(String nomeProduto, BigDecimal preco, String descricao, Integer quantidadeEstoque, Integer categoriaId) {
        this.nomeProduto = nomeProduto;
        this.preco = preco;
        this.descricao = descricao;
        this.quantidadeEstoque = quantidadeEstoque;
        this.categoriaId = categoriaId;
    }
    

    若允许,也可以给DTO添加无参构造器(注意final成员变量需要调整为非final,或改用Builder模式)。

  • 移除测试配置类的@EnableWebMvc:
    @EnableWebMvc会覆盖Spring Boot的自动配置,可能导致消息转换器配置异常。删除ProdutoControllerConfigurationTest中的@EnableWebMvc注解,依赖Spring Boot默认的Web配置即可。

  • 添加Accept请求头:
    虽然设置了contentType,但服务器可能期望特定的Accept头,在MockMVC请求中补充该配置:

    mockMvc.perform(MockMvcRequestBuilders.post("/api/produtos")
            .contentType(MediaType.APPLICATION_JSON_VALUE)
            .accept(MediaType.APPLICATION_JSON_VALUE)
            .content(objectMapper.writeValueAsString(criarProdutoDTO)))
            .andDo(MockMvcResultHandlers.print())
            .andExpect(MockMvcResultMatchers.status().isCreated());
    
  • 验证Jackson依赖完整性:
    确保项目依赖spring-boot-starter-web(默认包含Jackson相关组件),若单独引入Jackson,确认jackson-databind、jackson-annotations等依赖版本匹配。

  • 检查JSON序列化结果:
    在测试中打印序列化后的JSON字符串,确认键名与DTO的@JsonProperty注解匹配:

    String json = objectMapper.writeValueAsString(criarProdutoDTO);
    System.out.println(json);
    

内容的提问来源于stack exchange,提问作者Victor Hugo Pongolino

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.07 17:50:33