Cómo pasar un cliente HttpClient burlado en a.NET ¿prueba?


Tengo un servicio que usa Microsoft.Net.Http para recuperar algunos datos Json. ¡Órale!

Por supuesto, no quiero que mi prueba unitaria golpee el servidor real (de lo contrario, es una prueba de integración).

Aquí está mi ctor de servicio (que usa inyección de dependencias...)

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

No estoy seguro de cómo puedo burlarme de esto ... decir .. Moq o FakeItEasy.

Quiero asegurarme de que cuando mi servicio llame GetAsync o PostAsync.. entonces puedo falsificar esas llamadas.

Cualquier sugerencia de cómo puedo hacer ¿eso?

Espero no tener que hacer mi propio envoltorio .. porque eso es basura: (Microsoft no puede haber hecho un descuido con esto, ¿verdad?

(sí, es fácil hacer envoltorios .. he hecho antes ... pero es el momento!)

Author: Darrel Miller, 2014-03-06

4 answers

Puede reemplazar el controlador HttpMessageHandler del núcleo por uno falso. Algo que se parece a esto...

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

        }
    }

Y luego puede crear un cliente que utilizará el controlador falso.

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);
 91
Author: Darrel Miller,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-03-08 03:09:53

Sé que esta es una pregunta antigua, pero me tropecé con ella durante una búsqueda sobre este tema y encontré una solución muy buena para hacer las pruebas HttpClient más fácil.

Está disponible a través de nuget:

Https://github.com/richardszalay/mockhttp

PM> Install-Package RichardSzalay.MockHttp

Aquí hay un vistazo rápido al uso:

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'}

Más información en la página del proyecto github. Espero que esto pueda ser útil.

 17
Author: Fedaykin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-08-16 13:53:08

Solo haría un pequeño cambio en la respuesta de @Darrel Miller, que está usando la tarea .FromResult para evitar la advertencia sobre un método async esperando un operador await.

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
Author: Rui Taborda,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:34:21

Puede echar un vistazo a Microsoft Fakes, especialmente en la sección Shims. Con ellos, puede modificar los comportamientos de su propio HttpClient. El requisito previo es que estés usando VS Premium o Ultimate.

 1
Author: ElGauchooo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-03-06 11:53:44