webentwicklung-frage-antwort-db.com.de

Wie übergebe ich einen verspotteten HttpClient in einem .NET-Test?

Ich habe einen Dienst, der Microsoft.Net.Http, um einige Json Daten abzurufen. Groß!

Natürlich möchte ich nicht, dass mein Komponententest den tatsächlichen Server trifft (ansonsten ist das ein Integrationstest).

Hier ist mein Dienst ctor (der Abhängigkeitsinjektion verwendet ...)

public Foo(string name, HttpClient httpClient = null)
{
...
}

Ich bin nicht sicher, wie ich das verspotten kann mit ... sagen wir .. Moq oder FakeItEasy.

Ich möchte sicherstellen, dass ich diese Anrufe vortäuschen kann, wenn mein Dienst GetAsync oder PostAsync anruft.

Irgendwelche Vorschläge, wie ich das machen kann?

Ich muss nicht meinen eigenen Wrapper machen, weil das Mist ist :( Microsoft kann damit kein Versehen gemacht haben, oder?

(Ja, es ist einfach, Wrapper zu machen. Ich habe sie schon einmal gemacht. Aber es ist der Punkt!)

55
Pure.Krome

Sie können den zentralen HttpMessageHandler durch einen gefälschten ersetzen. Etwas, das so aussieht ...

public class FakeResponseHandler : DelegatingHandler
    {
        private readonly Dictionary<Uri, HttpResponseMessage> _FakeResponses = new Dictionary<Uri, HttpResponseMessage>(); 

        public void AddFakeResponse(Uri uri, HttpResponseMessage responseMessage)
        {
                _FakeResponses.Add(uri,responseMessage);
        }

        protected async override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, System.Threading.CancellationToken cancellationToken)
        {
            if (_FakeResponses.ContainsKey(request.RequestUri))
            {
                return _FakeResponses[request.RequestUri];
            }
            else
            {
                return new HttpResponseMessage(HttpStatusCode.NotFound) { RequestMessage = request};
            }

        }
    }

und dann können Sie einen Client erstellen, der den Fake-Handler verwendet.

var fakeResponseHandler = new FakeResponseHandler();
fakeResponseHandler.AddFakeResponse(new Uri("http://example.org/test"), new HttpResponseMessage(HttpStatusCode.OK));

var httpClient = new HttpClient(fakeResponseHandler);

var response1 = await httpClient.GetAsync("http://example.org/notthere");
var response2 = await httpClient.GetAsync("http://example.org/test");

Assert.Equal(response1.StatusCode,HttpStatusCode.NotFound);
Assert.Equal(response2.StatusCode, HttpStatusCode.OK);
95
Darrel Miller

Ich weiß, dass dies eine alte Frage ist, aber ich bin bei einer Suche zu diesem Thema darauf gestoßen und habe eine sehr gute Lösung gefunden, um das Testen von HttpClient zu vereinfachen.

Es ist über Nuget erhältlich:

https://github.com/richardszalay/mockhttp

PM> Install-Package RichardSzalay.MockHttp

Hier ist ein kurzer Blick auf die Verwendung:

var mockHttp = new MockHttpMessageHandler();

// Setup a respond for the user api (including a wildcard in the URL)
mockHttp.When("http://localost/api/user/*")
        .Respond("application/json", "{'name' : 'Test McGee'}"); // Respond with JSON

// Inject the handler or client into your application code
var client = new HttpClient(mockHttp);

var response = await client.GetAsync("http://localost/api/user/1234");
// or without await: var response = client.GetAsync("http://localost/api/user/1234").Result;

var json = await response.Content.ReadAsStringAsync();

// No network connection required
Console.Write(json); // {'name' : 'Test McGee'}

Weitere Infos auf der Github-Projektseite. Hoffe das kann nützlich sein.

18
Fedaykin

Ich würde nur eine kleine Änderung an der Antwort von @ Darrel Miller vornehmen, die Task.FromResult verwendet, um die Warnung zu vermeiden über eine asynchrone Methode, die einen wait-Operator erwartet.

public class FakeResponseHandler : DelegatingHandler
{
    private readonly Dictionary<Uri, HttpResponseMessage> _FakeResponses = new Dictionary<Uri, HttpResponseMessage>();

    public void AddFakeResponse(Uri uri, HttpResponseMessage responseMessage)
    {
        _FakeResponses.Add(uri, responseMessage);
    }

    protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, System.Threading.CancellationToken cancellationToken)
    {
        if (_FakeResponses.ContainsKey(request.RequestUri))
        {
            return Task.FromResult(_FakeResponses[request.RequestUri]);
        }
        else
        {
            return Task.FromResult(new HttpResponseMessage(HttpStatusCode.NotFound) { RequestMessage = request });
        }
    }
}
2
Rui Taborda

Sie können sich Microsoft Fakes ansehen, insbesondere den Abschnitt Shims-. Mit ihnen können Sie das Verhalten Ihres HttpClient selbst ändern. Voraussetzung ist, dass Sie VS Premium oder Ultimate verwenden.

1
ElGauchooo