WireMock对PostAsJsonAsync请求返回404,PostAsync却正常,原因何在?
PostAsJsonAsync调用WireMock返回404,但PostAsync正常的原因分析
我为测试目的搭建了WireMock API,最初使用PostAsJsonAsync调用端点:
var response = await _httpClient.PostAsJsonAsync("resorce/someRoute", obj);
但始终收到“Not Found”响应,调试REST请求和WireMock配置都未发现问题。换成手动构建StringContent再调用PostAsync则成功:
var json = new StringContent(JsonSerializer.Serialize(obj), Encoding.UTF8, "application/json"); var response = await _httpClient.PostAsync("resorce/someRoute", json);
这两种方式看似功能一致,问题出在以下几个细节差异上:
1. Content-Type头部的细微区别
PostAsJsonAsync与手动构建StringContent的Content-Type头部可能存在差异:
- 手动构建的
StringContent明确指定了application/json; charset=utf-8; - 而
PostAsJsonAsync的默认行为在不同.NET版本中有所不同:比如.NET Core早期版本中,它使用的JsonMediaTypeFormatter默认生成的Content-Type是application/json(不带charset=utf-8后缀)。
如果WireMock的Stub配置中精确匹配了包含charset的Content-Type,就会导致PostAsJsonAsync的请求无法匹配,返回404。
2. 序列化行为的差异
两种方式的JSON序列化逻辑可能不一致:
PostAsJsonAsync的序列化依赖项目配置:如果项目中引入了Newtonsoft.Json(比如.NET Framework或手动配置),它会使用Newtonsoft的序列化规则;而手动代码中用的是System.Text.Json的JsonSerializer。- 两者在属性命名策略(驼峰/PascalCase)、空值处理、JSON格式(空格、换行)等方面可能存在差异,导致WireMock对请求body的精确匹配失败。
3. WireMock的严格匹配规则
WireMock默认采用精确匹配策略,如果Stub配置中对请求的头部或body设置了严格匹配条件,任何细微差异都会导致请求不匹配:
- 比如Stub设置了
WithHeader("Content-Type", "application/json; charset=utf-8"),那么不带charset的请求就会被拒绝; - 如果Stub对body做了精确字符串匹配,而两种序列化生成的JSON格式不同,也会触发404。
验证与解决方法
- 查看WireMock请求日志:开启WireMock的请求日志功能,对比两种请求的完整头部和body,定位具体差异点;
- 调整WireMock匹配规则:
- 将Content-Type改为模糊匹配,比如使用
ContainsMatcher匹配application/json关键字; - 对body使用JsonPath或部分匹配,避免序列化细节影响匹配结果;
- 将Content-Type改为模糊匹配,比如使用
- 统一序列化逻辑:确保
PostAsJsonAsync和手动代码使用相同的序列化库(比如都用System.Text.Json),消除序列化差异。
内容的提问来源于stack exchange,提问作者Mohab Alnajjar
相关产品推荐
相关产品推荐

