c# - cref - ¿Cómo pasar un HttpClient burlado en una prueba.NET?
remarks c# (4)
Puede echarle 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é utilizando VS Premium o Ultimate.
Tengo un servicio que usa Microsoft.Net.Http
para recuperar algunos datos de Json
. ¡Estupendo!
Por supuesto, no quiero que mi prueba unitaria llegue al servidor real (de lo contrario, eso es una prueba de integración).
Aquí está mi servicio ctor (que usa inyección de dependencia ...)
public Foo(string name, HttpClient httpClient = null)
{
...
}
No estoy seguro de cómo puedo burlar esto con ... decir ... Moq
o FakeItEasy
.
Quiero asegurarme de que cuando mi servicio llame a GetAsync
o PostAsync
... entonces pueda falsificar esas llamadas.
¿Alguna sugerencia de cómo puedo hacer eso?
Estoy -esperando- no necesito hacer mi propia envoltura ... porque eso es una mierda :( Microsoft no puede haber hecho un descuido con esto, ¿verdad?
(Sí, es fácil hacer envoltorios ... ya los he hecho antes ... ¡pero es el punto!)
Puede reemplazar el núcleo HttpMessageHandler 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 puedes crear un cliente que usará 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);
Sé que esta es una pregunta antigua, pero me encontré con ella durante una búsqueda sobre este tema y encontré una solución muy buena para facilitar la prueba de HttpClient
.
Está disponible a través de nuget:
https://github.com/richardszalay/mockhttp
PM> Install-Package RichardSzalay.MockHttp
Aquí hay un vistazo rápido sobre el 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.
Simplemente haría un pequeño cambio en la respuesta de @Darrel Miller , que está usando Task.FromResult para evitar la advertencia sobre un método asíncrono esperando un operador en espera.
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 });
}
}
}