参数匹配不能与 NSubstitute 一起正常工作

Argument matching not working properly with NSubstitute

我有这段代码,无论如何我都无法让 httpClient return 字符串响应。

HttpClient httpClient = Substitute.For<HttpClient>();

httpClient.PostAsync("/login", Arg.Any<StringContent>())
          .Returns(this.StringResponse("{\"token\": \"token_content\"}"));

Console.WriteLine(await httpClient.PostAsync("/login", new StringContent(string.Empty)) == null); // True

这里是 StringResponse 如果有人想重现这个方法:

private HttpResponseMessage StringResponse(string content)
{
    var response = new HttpResponseMessage(HttpStatusCode.OK);

    if (content != null)
    {
        response.Content = new StringContent(content);
    }

    return response;
}

我做错了什么?

当我这样做时它会起作用

httpClient.PostAsync("/login", Arg.Any<StringContent>())
              .ReturnsForAnyArgs(this.StringResponse("{\"token\": \"token_content\"}"));

但我不需要任何参数,我需要其中一个是字符串 "/login",另一个是 StringContent.

类型

我试图在 Arg.Is 调用中添加一些更通用的内容,例如 HttpContent,但这也不起作用。

我在 .NET Core 上使用 NSubstitute 2.0.0-rc,但我也尝试在标准控制台应用程序上使用 NSubstitute 1.10.0 并得到相同的结果。

这里的问题是 public Task<HttpResponseMessage> PostAsync(string requestUri, HttpContent content) 方法不是虚拟的,NSubstitute 无法正确地 link 您的参数说明和 return 方法的值。这是所有基于 Castle.Core.

的模拟库的问题

重要的是 NSubstitute link 对执行堆栈中第一个虚拟方法的规范,结果是堆栈下方某处的 public override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) 方法。你 "lucky" 有相同的 return 类型。正如您所看到的,它有不同的参数,显然与您提供的参数不匹配。令人惊讶的是 ReturnsForAnyArgs() 有效,因为它不检查您提供的参数说明。