I am using Moq to create mocks for my unit tests but I am stuck when I have to create mock for getasync method of httpclient. Previously I was using SendAsync method and for that I could use the below code:
var mockResponse =
new HttpResponseMessage(HttpStatusCode.OK) {Content = new StringContent(expectedResponse)};
mockResponse.Content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
var mockHandler = new Mock<DelegatingHandler>();
mockHandler
.Protected()
.Setup<Task<HttpResponseMessage>>(
"SendAsync",
ItExpr.Is<HttpRequestMessage>(
message => message.Headers.Contains("Authorization")
&& message.Headers.Authorization.Parameter.Equals(accessToken)
&& message.Headers.Authorization.Scheme.Equals("Bearer")
&& message.RequestUri.AbsoluteUri.Contains(baseUrl)
),
ItExpr.IsAny<CancellationToken>())
.Returns(Task.FromResult(mockResponse));
Now I have a method:
private async Task<List<Model>> GetData()
{
string url = url;
_httpClient.BaseAddress = new Uri(url);
_httpClient.DefaultRequestHeaders.Add(Headers.AuthorizationHeader, "Bearer" + "token");
var response = await _httpClient.GetAsync(url);
response.EnsureSuccessStatusCode();
return await response.Content.ReadAsAsync<List<Model>>();
}
Now can I create mock for this method (getasync)? Any help?
HttpClient's extensibility lies in the HttpMessageHandler passed to the constructor. Its intent is to allow platform specific implementations, but you can also mock it. There's no need to create a decorator wrapper for HttpClient.
Returns("my_ticket"); Mock<HttpRequestMessage> req = new Mock<HttpRequestMessage>(); req. Setup(m => m. CreateResponse( HttpStatusCode. OK, "value")) .
GetAsync(String, HttpCompletionOption) Send a GET request to the specified Uri with an HTTP completion option as an asynchronous operation. GetAsync(String, CancellationToken) Send a GET request to the specified Uri with a cancellation token as an asynchronous operation.
The HTTP request is sent out, and HttpClient. GetAsync returns an uncompleted Task .
Your best alternative would be to create a Adapter/wrapper for HttpClient and mock that in this case. Something like
With the help of extension methods, mocking HTTP requests can be just as easy as mocking a service method. HttpClient with vanilla Moq HttpClient itself is merely a set of helpers wrapping an HttpMessageHandler; all requests ultimately go through the handler’s sole SendAsync method.
To demonstrate httpclient mocking using Xunit, I am creating a simple web API application and adding a new test (XUnit) project. Let's introduce IHttpClientHelper interface to mock httpclient. Here you can see HttpClient property as well, which is used to hold the mocked HttpMessageHandler object.
We mock a call to the SendAsync () function and provide a response to return with the ReturnAsync () method. In the Setup<> () method, the first parameter is the name of the method that is being mocked. Next, we match each parameter to the "SendAsync" method with an expression.
Internally GetAsync
will eventually call SendAsync
.
public Task<HttpResponseMessage> GetAsync(Uri requestUri, HttpCompletionOption completionOption,
CancellationToken cancellationToken)
{
return SendAsync(new HttpRequestMessage(HttpMethod.Get, requestUri), completionOption, cancellationToken);
}
Source code
Loosen the ItExpr
expectation and you should be able to get it to behave as expected.
Using the originally provided example
mockHandler
.Protected()
.Setup<Task<HttpResponseMessage>>(
"SendAsync",
ItExpr.IsAny<HttpRequestMessage>(),
ItExpr.IsAny<CancellationToken>()
)
.ReturnsAsync(mockResponse);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With