web-dev-qa-db-fra.com

Impossible de se moquer de httpclient postaSync () dans des tests unitaires

J'écris des cas de test utilisant Xunit et MOQ.

J'essaie de se moquer postasync () de httpclient, mais je reçois une erreur.

Vous trouverez ci-dessous le code utilisé pour la moqueur:

   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);
    }

Erreur:

Expression non prise en charge: repo => repo.postasync (it.isany (), it.isany ()) Membres non directs (ici: httpclient.postasync) ne peut pas être utilisé dans les expressions de configuration/vérification.

Capture d'écran:

enter image description here

6
chandra sekhar

Le problème que vous rencontrez indique un couplage élevé et vous le résolvez en introduisant une abstration intermédiaire. Vous voudrez peut-être créer une classe qui agrége le httpClient et expose le postaSync via une méthode d'interface:

// Now you mock this interface instead, which is a pretty simple task.
// I suggest also abstracting away from an HttpResponseMessage
// This would allow you to swap for any other transport in the future. All 
// of the response error handling could be done inside the message transport 
// class.  
public interface IMessageTransport
{
    Task SendMessageAsync(string message);
}

// In ADLS_Operations ctor:
public ADLS_Operations(IMessageTransport messageTransport)
{ 
    //...
}

public class HttpMessageTransport : IMessageTransport
{
    public HttpMessageTransport()
    {
        this.httpClient = //get the http client somewhere.
    }

    public Task SendMessageAsync(string message)
    {
        return this.httpClient.PostAsync(message);
    }
}
0
Mokona Modoki

Visiter Blog

Il y a une prise en charge intégrée pour appliquer des conditions sur les propriétés httpmethod et demandeurs de HTTPRequestMessage. De cette façon, nous pouvons se moquer de httpget, httppost et d'autres verbes pour divers chemins à l'aide de la méthode de fin de finition telle que décrite ci-dessous.

_httpMessageHandler.Protected()
      .Setup<Task<HttpResponseMessage>>("SendAsync", true,          
      *// Specify conditions for httpMethod and path
      ItExpr.Is<HttpRequestMessage>(req => req.Method == HttpMethod.Get
           && req.RequestUri.AbsolutePath.EndsWith($"{path}"))),*
      ItExpr.IsAny<CancellationToken>())
      .ReturnsAsync(new HttpResponseMessage
      {
           StatusCode = HttpStatusCode.OK,
           Content = new StringContent("_0Kvpzc")
       });
0

Au fur et à mesure que d'autres réponses expliquent, vous devez vous moquer du HTTPMessageHandler ou de la httpClientfactory, pas de httpClient. Ceci est un scénario tel que quelqu'un a créé une bibliothèque d'assistrations pour des cas , Moq.contrib.httpclient .

Copier de la General Usage Exemple pour 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));

Pour 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;
    });
0
Panagiotis Kanavos