13

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?

1
  • internally GetAsync will eventually call SendAsync. Loosen the ItExpr and you should be able to get it to behave as expected. Commented Oct 31, 2018 at 11:00

1 Answer 1

22

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);
Sign up to request clarification or add additional context in comments.

5 Comments

And same is the case for PostAsync and PostJsonAsync?
@Ask Yes. If you check the source code you will see that SendAsync is the main method for making requests. all the others eventually call that method
and more thing, I know it's not related to this question and should be another question but do we have any way to create mock of static methods (extension methods)
@Ask Moq is unable to mock static/extension methods.
@Ask review the source code of the extension, if available and try to craft a safe path through its invocation.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.