【发布时间】:2021-08-07 02:01:34
【问题描述】:
我正在尝试使用 Substitute 来模拟 HttpClient。代码如下:
public static HttpClient GetHttpClient(bool isSucess = true, string methodType = "GET")
{
var mockIHttpMessageHandler = Substitute.For<IMockHttpMessageHandler>();
var mockHttpMessageHandler = Substitute.For<MockHttpMessageHandler>(mockIHttpMessageHandler);
var httpResponse = Substitute.For<HttpResponseMessage>();
httpResponse.Content = new StringContent("\"test\"");
if (isSucess)
httpResponse.StatusCode = HttpStatusCode.OK;
else
httpResponse.StatusCode = HttpStatusCode.NotFound;
var mockHttpClient = Substitute.For<HttpClient>(mockHttpMessageHandler);
mockHttpClient.BaseAddress = new Uri("http://localhost");
if(methodType != "POST"){
mockHttpClient.GetAsync(Arg.Any<Uri>()).ReturnsForAnyArgs(httpResponse);
}
return mockHttpClient;
}
但是,我在这一行遇到了错误:
mockHttpClient.GetAsync(Arg.Any<Uri>()).ReturnsForAnyArgs(httpResponse);
错误是
NSubstitute.Exceptions.RedundantArgumentMatcherException: '一些 参数说明(例如 Arg.Is、Arg.Any)在 最后一次通话。
这通常是由使用参数规范和对成员的调用引起的 NSubstitute 不处理(例如非虚拟成员或调用 一个不是替代品的实例),或用于其他目的 指定调用(例如使用 arg 规范作为返回值)。为了 示例:
var sub = Substitute.For<SomeClass>(); var realType = new MyRealType(sub); // INCORRECT, arg spec used on realType, not a substitute: realType.SomeMethod(Arg.Any<int>()).Returns(2); // INCORRECT, arg spec used as a return value, not to specify a call: sub.VirtualMethod(2).Returns(Arg.Any<int>()); // INCORRECT, arg spec used with a non-virtual method: sub.NonVirtualMethod(Arg.Any<int>()).Returns(2); // CORRECT, arg spec used to specify virtual call on a substitute: sub.VirtualMethod(Arg.Any<int>()).Returns(2);要解决此问题,请确保您仅在调用中使用参数规范 给替补。如果您的替代品是一个班级,请确保该成员是 虚拟的。
另一个可能的原因是参数规范类型不匹配 实际的参数类型,但代码由于隐式转换而编译。 例如,使用了 Arg.Any(),但使用了 Arg.Any() 必填。
注意:此异常的原因可能是在先前执行的 测试。使用下面的诊断来查看任何冗余 arg 的类型 规范,然后找出它们的创建位置。
诊断信息:
剩余(非绑定)参数规范: 任何 Uri
所有参数说明: 任何 Uri
他们是否建议我需要更改 getAsync 方法? GetAsync没有虚方法
编辑:
我也尝试过如下删除 HttpClient 的 NSubstitute,但还是出现同样的错误:
public static HttpClient GetHttpClient(bool isSucess = true, string methodType = "GET")
{
var mockIHttpMessageHandler = Substitute.For<IMockHttpMessageHandler>();
var mockHttpMessageHandler = Substitute.For<MockHttpMessageHandler>(mockIHttpMessageHandler);
var httpResponse = Substitute.For<HttpResponseMessage>();
httpResponse.Content = new StringContent("\"test\"");
if (isSucess)
httpResponse.StatusCode = HttpStatusCode.OK;
else
httpResponse.StatusCode = HttpStatusCode.NotFound;
var httpClient = new HttpClient(mockHttpMessageHandler);
httpClient = new Uri("http://localhost");
if(methodType != "POST"){
httpClient .GetAsync(Arg.Any<Uri>()).ReturnsForAnyArgs(httpResponse);
}
return httpClient
}
【问题讨论】:
-
所有调用 GET POST 等调用
Send方法。但是,我建议不要嘲笑 httpclient。使用实际的httpclient。模拟处理程序(客户端调用)并让它处理请求。 -
@Nkosi 谢谢,我在没有使用 NSubstitute 的情况下尝试过,但我得到了同样的错误
-
尝试将NSubstitute.Analyzers 包添加到您的测试项目中。它也许能够找出造成这种情况的原因。
标签: c# unit-testing httpclient virtual nsubstitute