Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

858
Views
Unable to Mock HttpClient PostAsync() in unit tests

I am writing test cases using xUnit and Moq.

I am trying to mock PostAsync() of HttpClient, but I get an error.

Below is the code used for mocking:

   public TestADLS_Operations()
    {
        var mockClient = new Mock<HttpClient>();
        mockClient.Setup(repo => repo.PostAsync(It.IsAny<string>(), It.IsAny<HttpContent>())).Returns(() => Task.FromResult(new HttpResponseMessage(HttpStatusCode.OK)));

        this._iADLS_Operations = new ADLS_Operations(mockClient.Object);
    }

Error:

Unsupported expression: repo => repo.PostAsync(It.IsAny(), It.IsAny()) Non-overridable members (here: HttpClient.PostAsync) may not be used in setup / verification expressions.

Screenshot:

enter image description here

over 4 years ago · Santiago Trujillo
3 answers
Answer question

0

Non-overridable members (here: HttpClient.PostAsync) may not be used in setup / verification expressions.

I also tried to mock the HttpClient the same way you did, and I got the same error message.


Solution:

Instead of mocking the HttpClient, mock the HttpMessageHandler.

Then give the mockHttpMessageHandler.Object to your HttpClient, which you then pass to your product code class. This works because HttpClient uses HttpMessageHandler under the hood:

// Arrange
var mockHttpMessageHandler = new Mock<HttpMessageHandler>();
mockHttpMessageHandler.Protected()
    .Setup<Task<HttpResponseMessage>>("SendAsync", ItExpr.IsAny<HttpRequestMessage>(), ItExpr.IsAny<CancellationToken>())
    .ReturnsAsync(new HttpResponseMessage { StatusCode = HttpStatusCode.OK });

var client = new HttpClient(mockHttpMessageHandler.Object);
this._iADLS_Operations = new ADLS_Operations(client);

Note: You will also need a

using Moq.Protected;

at the top of your test file.

Then you can call your method that uses PostAsync from your test, and PostAsync will return an HTTP status OK response:

// Act
var returnedItem = this._iADLS_Operations.MethodThatUsesPostAsync(/*parameter(s) here*/);

Advantage: Mocking HttpMessageHandler means that you don't need extra classes in your product code or your test code.


Helpful resources:

  1. Unit Testing with the HttpClient
  2. How to mock HttpClient in your .NET / C# unit tests
over 4 years ago · Santiago Trujillo Report

0

As other answers explain, you should mock the HttpMessageHandler or the HttpClientFactory, not HttpClient. This is such a common scenario that someone created a helper library for both cases, Moq.Contrib.HttpClient.

Copying from the General Usage example for HttpClient :

// All requests made with HttpClient go through its handler's SendAsync() which we mock
var handler = new Mock<HttpMessageHandler>();
var client = handler.CreateClient();

// A simple example that returns 404 for any request
handler.SetupAnyRequest()
    .ReturnsResponse(HttpStatusCode.NotFound);

// Match GET requests to an endpoint that returns json (defaults to 200 OK)
handler.SetupRequest(HttpMethod.Get, "https://example.com/api/stuff")
    .ReturnsResponse(JsonConvert.SerializeObject(model), "application/json");

// Setting additional headers on the response using the optional configure action
handler.SetupRequest("https://example.com/api/stuff")
    .ReturnsResponse(bytes, configure: response =>
    {
        response.Content.Headers.LastModified = new DateTime(2018, 3, 9);
    })
    .Verifiable(); // Naturally we can use Moq methods as well

// Verify methods are provided matching the setup helpers
handler.VerifyAnyRequest(Times.Exactly(3));

For HttpClientFactory :

var handler = new Mock<HttpMessageHandler>();
var factory = handler.CreateClientFactory();

// Named clients can be configured as well (overriding the default)
Mock.Get(factory).Setup(x => x.CreateClient("api"))
    .Returns(() =>
    {
        var client = handler.CreateClient();
        client.BaseAddress = ApiBaseUrl;
        return client;
    });
over 4 years ago · Santiago Trujillo Report

0

Instead of directly using a HttpClient instance in your code, use a IHttpClientFactory. In your tests, you can then create your own implementation of IHttpClientFactory that sends back a HttpClient which connects to a TestServer.

Here's an example of what your Fake Factory could look like:

public class InMemoryHttpClientFactory: IHttpClientFactory
{
    private readonly TestServer _server;

    public InMemoryHttpClientFactory(TestServer server)
    {
        _server = server;
    }

    public HttpClient CreateClient(string name)
    {
        return _server.CreateClient();
    }
}

You can then setup a TestServer in your tests and have your custom IHttpClientFactory create clients for that server:

public TestADLS_Operations()
{
    //setup TestServer
    IWebHostBuilder hostBuilder = new WebHostBuilder()
        .Configure(app => app.Run(
        async context =>
    {
        // set your response headers via the context.Response.Headers property
        // set your response content like this:
        byte[] content = Encoding.Unicode.GetBytes("myResponseContent");
        await context.Response.Body.WriteAsync(content);
    }));
    var testServer = new TestServer(hostBuilder)

    var factory = new InMemoryHttpClientFactory(testServer);
    _iADLS_Operations = new ADLS_Operations(factory);

    [...]
}
over 4 years ago · Santiago Trujillo Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!