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

如何使用Moq根据参数Mock两个不同的API POST请求?

如何Mock带StringContent参数的POST API调用并区分有效/无效ID

需求背景

需要Mock外部POST类型的API调用,分别测试传入有效ID(如1)和无效ID(如-1)时的代码逻辑,当前API参数以StringContent形式传递,且所有Mock逻辑集中在一个扩展类中。


核心解决方案

要区分不同的documentId,关键是在Mock的条件判断中解析POST请求的StringContent内容,提取出documentId后再做匹配判断。

1. 添加请求内容解析的辅助方法

先写一个工具方法,从HttpRequestMessage中读取并解析出documentId:

private static int? GetDocumentIdFromRequest(HttpRequestMessage request)
{
    if (request.Content is not StringContent stringContent) return null;
    
    // 测试场景下同步读取内容,避免异步表达式树的问题
    var contentJson = stringContent.ReadAsStringAsync().GetAwaiter().GetResult();
    var payload = JsonSerializer.Deserialize<dynamic>(contentJson);
    return payload?.documentId?.Value;
}

2. 分别配置有效/无效ID的Mock逻辑

修改集中管理的MockApiCalls方法,添加两个不同条件的Mock分支:

private static void MockApiCalls(Mock<HttpMessageHandler> mock) 
{
    // Mock 有效ID(1)的响应:返回成功结果
    mock.Protected()
        .Setup<Task<HttpResponseMessage>>("SendAsync", 
            ItExpr.Is<HttpRequestMessage>(e => 
                e.Method == HttpMethod.Post &&
                e.RequestUri.ToString().Contains("/api/GetDocInfo") &&
                GetDocumentIdFromRequest(e) == 1), 
            ItExpr.IsAny<CancellationToken>())
        .ReturnsAsync(new HttpResponseMessage(HttpStatusCode.OK)
        {
            Content = new StringContent(JsonSerializer.Serialize(new { /* 填入业务侧预期的成功响应结构 */ }), Encoding.UTF8, "application/json")
        });

    // Mock 无效ID(-1)的响应:返回错误结果
    mock.Protected()
        .Setup<Task<HttpResponseMessage>>("SendAsync", 
            ItExpr.Is<HttpRequestMessage>(e => 
                e.Method == HttpMethod.Post &&
                e.RequestUri.ToString().Contains("/api/GetDocInfo") &&
                GetDocumentIdFromRequest(e) == -1), 
            ItExpr.IsAny<CancellationToken>())
        .ReturnsAsync(new HttpResponseMessage(HttpStatusCode.NotFound)
        {
            Content = new StringContent(JsonSerializer.Serialize(new { Message = "无效文档ID" }), Encoding.UTF8, "application/json")
        });
}

3. 编写对应的测试用例

在测试类中补充无效ID的验证方法:

[Test]
public async Task ShouldReturnNotFoundForInvalidDocument()
{
    var request = new GetInfoQuery(-1);
    var result = await SendAsync(request);

    Assert.NotNull(result);
    Assert.False(result.IsSuccess);
    // 可额外验证错误信息是否符合预期
}

注意事项

  • 解析Content时使用GetAwaiter().GetResult()是因为表达式树中无法直接使用await,测试场景下同步读取是安全的
  • 确保JsonSerializer的配置和业务代码中的序列化配置一致,避免反序列化失败
  • 如果需要覆盖更多ID场景,只需在MockApiCalls中新增对应条件的Mock分支即可

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 06:52:51