Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

857
Visualizações
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 Respostas
Responde à pergunta

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 Relatório

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 Relatório

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 Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda