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

Spring REST Docs记录无请求体PUT接口时查询参数异常显示问题

解决Spring REST Docs误将查询参数渲染为PUT请求体的问题

嘿,这个坑我之前踩过!你遇到的问题其实是Spring MockMvc和REST Docs的默认行为共同导致的,咱们一步步说清楚:

为什么会出现这个现象?

当你在测试PUT请求时使用.param("currentUser", "johndoe")方法,Spring MockMvc的默认逻辑会把这个参数同时作为查询参数和表单参数处理:

  • 一方面,它会把参数追加到URL的查询字符串里(这符合你的API设计);
  • 另一方面,因为PUT请求默认的Content-Type是application/x-www-form-urlencoded,MockMvc会自动把参数塞进请求体里,而Spring REST Docs会忠实地记录下这个请求体内容,于是就出现了你看到的奇怪结果。

怎么解决?

有两个简单的办法,任选其一就行:

1. 明确使用查询参数方法

把测试代码里的.param()换成.queryParam(),这样MockMvc只会把参数放到查询字符串中,不会生成表单请求体:

mockMvc.perform(put("/posts/{id}/read", 42)
        .queryParam("currentUser", "johndoe"))
        .andExpect(status().isOk())
        .andDo(document("mark-post-as-read",
                pathParameters(
                        parameterWithName("id").description("The ID of the post to mark as read")
                ),
                requestParameters(
                        parameterWithName("currentUser").description("The login ID of the current user")
                )
        ));

2. 显式指定无请求体或正确的Content-Type

如果你习惯用.param(),可以明确设置请求体为空,同时指定一个非表单的Content-Type(比如application/json),这样MockMvc就不会自动生成表单请求体:

mockMvc.perform(put("/posts/{id}/read", 42)
        .param("currentUser", "johndoe")
        .content("") // 空请求体
        .contentType(MediaType.APPLICATION_JSON))
        .andExpect(status().isOk())
        .andDo(document("mark-post-as-read",
                pathParameters(
                        parameterWithName("id").description("The ID of the post to mark as read")
                ),
                requestParameters(
                        parameterWithName("currentUser").description("The login ID of the current user")
                )
        ));

另外要注意:在生成文档的snippets()配置里,不要包含requestFields()片段,这样REST Docs就不会生成请求体相关的内容啦。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 06:59:49