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

SpringBootTest MockMvc测试HttpMediaTypeNotSupportedException问题

问题根因

两个报错和你设置的Content-Type、Accept请求头无关,是测试配置缺失导致的独立问题:

415 Unsupported Media Type 成因

@SpringBootTest(classes = Controller.class) 配置只会加载你指定的Controller单个Bean,不会触发Spring Web层的自动配置流程,负责解析JSON请求的MappingJackson2HttpMessageConverter(Jackson消息转换器)不会被注册。没有这个转换器时,Spring无法识别application/json类型的请求,哪怕请求头配置正确也会判定媒体类型不支持,返回415。日志里响应头Accept字段列出的所有支持媒体类型里没有application/json,也能佐证这一点。

403 Forbidden 成因

移除addFilters = false后,Spring Security的过滤器链会生效,默认开启的CSRF防护会拦截所有没有携带合法CSRF Token的POST类修改请求,直接返回403,请求根本不会进入控制器方法,所以日志里Handler字段显示为null。

修复方案

按以下步骤调整即可解决问题:

  • 替换测试类的上下文加载注解,做Web层接口测试优先使用@WebMvcTest(Controller.class)代替原有的@SpringBootTest(classes = Controller.class)。@WebMvcTest是Spring Boot专门提供的Web层切片测试注解,会自动配置MockMvc、JSON消息转换器、所有Web层相关组件,加载速度远快于全量上下文的@SpringBootTest,你已经用@MockBean标注的Service层Mock对象也能正常注入。
    如果需要加载完整应用上下文做集成测试,直接去掉@SpringBootTest的classes属性,让Spring自动扫描主启动类加载全量配置即可。
  • 解决CSRF拦截问题,引入spring-security-test依赖后,在构建MockMvc请求时追加.with(SecurityMockMvcRequestPostProcessors.csrf())携带合法CSRF Token即可,这种方式和生产环境的校验逻辑一致,测试结果更准确。如果测试场景不需要走安全过滤器链,也可以保留@AutoConfigureMockMvc(addFilters = false)配置,跳过所有过滤器校验,前提是已经替换为@WebMvcTest或正确加载了Web层自动配置解决415问题。
  • 可选优化:控制器方法里手动校验Errors的逻辑属于重复代码,Spring默认会在参数校验失败时抛出MethodArgumentNotValidException,可以通过@RestControllerAdvice做全局异常拦截统一返回400响应,不需要在每个接口方法内重复写判断逻辑。
修正后的测试类参考代码
@WebMvcTest(Controller.class)
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 {
        CreateAgencyRequest request = CreateAgencyRequest.builder()
                .name("name<script>")
                .primaryEmail("test@mail.com")
                .build();

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

注意:代码里的请求实体类名需要和你实际定义的类名保持一致,示例中使用了你提供的CreateAgencyRequest作为实体类名。如果静态导入SecurityMockMvcRequestPostProcessors.csrf方法,请求构建部分可以直接简写为.with(csrf())。

内容的提问来源于stack exchange,提问作者tusharRawat

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 12:27:25