如何在.NETtesting中传递一个模拟的HttpClient?
我有一个服务使用Microsoft.Net.Http
来检索一些Json
数据。 大!
当然,我不希望我的unit testing打到实际的服务器(否则,这是一个集成testing)。
这是我的服务ctor(它使用dependency injection…)
public Foo(string name, HttpClient httpClient = null) { ... }
我不知道我怎么可以嘲笑…说… Moq
或FakeItEasy
。
我想确保当我的服务调用GetAsync
或PostAsync
..然后我可以伪造这些调用。
任何build议我怎么能做到这一点?
我是 – 希望 – 我不需要做我自己的包装..因为这是废话:(微软不能做出这个疏忽,对吧?
(是的,制作包装纸很容易..我之前做过这些,但这是重点!)
你可以用一个假的replace核心的HttpMessageHandler。 看起来像这样的东西…
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}; } } }
然后您可以创build一个将使用假处理程序的客户端。
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);
我知道这是一个古老的问题,但是在search这个主题的过程中我偶然发现了这个问题,并发现了一个非常好的解决scheme,使testingHttpClient
变得更加简单。
它可以通过nuget获得:
https://github.com/richardszalay/mockhttp
PM> Install-Package RichardSzalay.MockHttp
以下是对使用情况的简要介绍:
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'}
有关github项目页面的更多信息。 希望这可以是有用的。
我只是对@Darrel Miller的答案做一个小的修改,即使用Task.FromResult来避免预期等待操作符的asynchronous方法的警告。
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 }); } } }
你可以看看微软的假货 ,特别是在Shims
section。 有了它们,你可以修改你的HttpClient本身的行为。 先决条件是,您正在使用VS Premium或Ultimate。