参数匹配与NSubstitute

时间:2016-09-30 18:31:01

标签: c# .net mocking httpclient nsubstitute

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

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并获得相同的结果。

1 个答案:

答案 0 :(得分:6)

这里的问题是public Task<HttpResponseMessage> PostAsync(string requestUri, HttpContent content)方法不是虚拟的,并且NSubstitute无法正确链接您的参数规范和返回值到方法。这是基于Castle.Core的所有模拟库的问题。

重要的是NSubstitute将规范链接到执行堆栈中的第一个虚拟方法,而这个方法在堆栈的某个地方被证明是public override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)方法。你是幸运的&#34;在其中具有相同的返回类型。正如你所看到的,它有不同的论点,显然与你提供的论点不相符。令人惊讶的是ReturnsForAnyArgs()有效,因为它没有检查您提供的参数规范。