I have a service which uses Microsoft.Net.Http
to retrieve some Json
data. Great!
Of course, I don't want my unit test hitting the actual server (otherwise, that's an integration test).
Here's my service ctor (which uses dependency injection...)
public Foo(string name, HttpClient httpClient = null) { ... }
I'm not sure how I can mock this with ... say .. Moq
or FakeItEasy
.
I want to make sure that when my service calls GetAsync
or PostAsync
.. then i can fake those calls.
Any suggestions how I can do that?
I'm -hoping- i don't need to make my own Wrapper .. cause that's crap :( Microsoft can't have made an oversight with this, right?
(yes, it's easy to make wrappers .. i've done them before ... but it's the point!)
Mocking HttpClient is possible although an arduous task. Luckily there is still a great way to unit test the code. The solution is to mock HttpMessageHandler and pass this object to the HttpClient constructor. When we use the message handler to make HTTP requests, we achieve our unit testing goals.
HttpClient's extensibility lies in the HttpMessageHandler passed to the constructor. Its intent is to allow platform specific implementations, but you can also mock it. There's no need to create a decorator wrapper for HttpClient.
Returns("my_ticket"); Mock<HttpRequestMessage> req = new Mock<HttpRequestMessage>(); req. Setup(m => m. CreateResponse( HttpStatusCode. OK, "value")) .
Unit testing is a powerful way to ensure that your code works as intended. It's a great way to combat the common “works on my machine” problem. Using Moq, you can mock out dependencies and make sure that you are testing the code in isolation. Moq is a mock object framework for .
You can replace the core HttpMessageHandler with a fake one. Something that looks like this...
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 }); } } }
and then you can create a client that will use the fake handler.
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);
I know that this is an old question but I stumbled with it during a search on this topic and found a very nice solution to make testing HttpClient
easier.
It is available via nuget:
https://github.com/richardszalay/mockhttp
PM> Install-Package RichardSzalay.MockHttp
Here is a quick look on the usage:
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'}
More info on the github project page. Hope this can be useful.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With