Pure.Krome Pure.Krome - 1 year ago 281
C# Question

How to pass in a mocked HttpClient in a .NET test?

I have a service which uses

to retrieve some
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 ..

I want to make sure that when my service calls
.. 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!)

Answer Source

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)

        protected async override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, System.Threading.CancellationToken cancellationToken)
            if (_FakeResponses.ContainsKey(request.RequestUri))
                return _FakeResponses[request.RequestUri];
                return 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(response2.StatusCode, HttpStatusCode.OK);