如何验证传递给HttpClient.PostAsJsonAsync的请求对象?
解决方案
原测试代码的问题在于错误地在SendAsync的验证参数中添加了SearchRequest类型的匹配项——SendAsync方法的参数只有HttpRequestMessage和CancellationToken,根本不存在SearchRequest参数,这导致验证逻辑完全不生效。
正确的思路是:PostAsJsonAsync会将SearchRequest序列化为HttpRequestMessage的Content内容,因此需要从HttpRequestMessage中读取并反序列化出SearchRequest对象,再验证其属性值。
修改后的测试代码
public async Task Test() { // Arrange var handlerMock = new Mock<HttpClientHandler>(); handlerMock.Protected() .Setup<Task<HttpResponseMessage>>( "SendAsync", ItExpr.IsAny<HttpRequestMessage>(), ItExpr.IsAny<CancellationToken>() ) .ReturnsAsync(new HttpResponseMessage { StatusCode = HttpStatusCode.OK, Content = new StringContent("{'foo':'bar'}", Encoding.UTF8, "application/json") }); httpClient = new HttpClient(handlerMock.Object); // Act var criteria = new Criteria(); await SomeMethodToTestAsync(criteria); // Assert var expectedPublishedDate = new DateOnly(2021, 10, 17); handlerMock.Protected().Verify( "SendAsync", Times.Exactly(1), ItExpr.Is<HttpRequestMessage>(req => req.Method == HttpMethod.Post && req.RequestUri.ToString() == "https://example.com" && // 可选:验证请求URL ValidateSearchRequestContent(req.Content, expectedPublishedDate) ), ItExpr.IsAny<CancellationToken>() ); } private bool ValidateSearchRequestContent(HttpContent content, DateOnly expectedDate) { // 读取Content中的JSON字符串 var jsonContent = content.ReadAsStringAsync().Result; // 反序列化为SearchRequest对象(注意匹配序列化配置) var searchRequest = JsonSerializer.Deserialize<SearchRequest>(jsonContent, new JsonSerializerOptions { PropertyNameCaseInsensitive = true, // 避免JSON属性大小写不匹配问题 Converters = { new DateOnlyConverter() } // 如果需要自定义DateOnly序列化,添加对应的转换器 }); // 验证目标属性 return searchRequest != null && searchRequest.PublishedDateStart == expectedDate; }
关键说明
- 移除错误的参数匹配:删除原代码中
ItExpr.Is<SearchRequest>(...)这一行,因为SendAsync没有该参数。 - 从Content中解析请求对象:通过
HttpContent.ReadAsStringAsync()读取序列化后的JSON,再反序列化为SearchRequest,之后验证属性值。 - 匹配序列化配置:如果待测试方法中使用了自定义的JSON序列化配置(比如Newtonsoft.Json而非System.Text.Json),需要在反序列化时使用对应的工具(如
JsonConvert.DeserializeObject),确保解析结果正确。 - 可选的URL验证:添加
req.RequestUri.ToString() == "https://example.com"可以进一步验证请求的目标地址是否正确。
内容的提问来源于stack exchange,提问作者arjun
相关产品推荐
相关产品推荐

