Reputation: 2214
I have trouble mocking with Moq
.
Normally having a HttpClient
I would mock it by injecting the HttpClient
in the base class like this:
public class MyClass
{
private readonly HttpClient httpClient;
public MyClass(HttpClient httpClient)
{
this.httpClient = httpClient;
}
}
But now I have different functions in my class MyClass
that need a custom HttpClientHandler
like this:
HttpClientHandler httpClientHandler = new HttpClientHandler();
...
using var client = new HttpClient(httpClientHandler);
If I'd simply inject a HttpClient
in MyClassTest
with var service = new MyClass(httpMock.Object);
, then the httpClient would be overwritten.
What would be the right way to test my functions and not making a real HTTP-call?
Upvotes: 1
Views: 3576
Reputation: 11
What would be the right way to test my functions and not making a real HTTP-call?
Maybe not what you are looking for, but I suggest you consider Andrew Lock's wisdom - don't unit-test API/MVC controllers in ASP.NET Core.
For .NET Core (and .NET 5) you should avoid mocking HttpClient if you are testing a controller class.
If a controller class is not your SUT, I would wrap the HttpClient in a facade interface and mock that.
Upvotes: 1
Reputation: 22849
I suppose you are using typed client approach of the IHttpClientFactory
. That's why your MyClass
ctor receives an HttpClient
instance.
If you need to mock that HttpClient
then I suggest you to follow Hamid Mosalla's advice.
In short there is a helper class, which makes HttpMessageHandler
's SendAsync
mockable (without the need to use the Moq.Protected).
public class FakeHandler: HttpMessageHandler
{
public virtual HttpResponseMessage Send(HttpRequestMessage request)
{
throw new NotImplementedException();
}
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
return Task.FromResult(Send(request));
}
}
You can use this helper class like this to mock any HttpClient
call:
var httpResponse = new HttpResponseMessage
{
Content = new StringContent(JsonConvert.SerializeObject(responseObject))
};
var mockHandler = new Mock<FakeHandler> { CallBase = true };
mockHandler
.Setup(handler => handler.Send(It.IsAny<HttpRequestMessage>()))
.Returns(httpResponse);
var mockHttpClient = new HttpClient(mockHandler.Object);
var SUT = new MyClass(mockHttpClient);
Upvotes: 1