I am trying to use NSubstitute to mock HttpClient. Here's the code:
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;
}
However, I got an error at this line:
mockHttpClient.GetAsync(Arg.Any<Uri>()).ReturnsForAnyArgs(httpResponse);
And the error is
NSubstitute.Exceptions.RedundantArgumentMatcherException: 'Some argument specifications (e.g. Arg.Is, Arg.Any) were left over after the last call.
This is often caused by using an argument spec with a call to a member NSubstitute does not handle (such as a non-virtual member or a call to an instance which is not a substitute), or for a purpose other than specifying a call (such as using an arg spec as a return value). For example:
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);
To fix this make sure you only use argument specifications with calls to substitutes. If your substitute is a class, make sure the member is virtual.
Another possible cause is that the argument spec type does not match the actual argument type, but code compiles due to an implicit cast. For example, Arg.Any() was used, but Arg.Any() was required.
NOTE: the cause of this exception can be in a previously executed test. Use the diagnostics below to see the types of any redundant arg specs, then work out where they are being created.
Diagnostic information:
Remaining (non-bound) argument specifications: any Uri
All argument specifications: any Uri
Are they suggesting I need to change the getAsync
method? There's no virtual method for GetAsync
Edit:
I have also tried to remove NSubstitute for HttpClient as follows, but I still got the same error:
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
}