FakeHttpMessageHandler seamlessly fakes http request sent from System.Net.Http.HttpClient for purpose of unit testing code that previously could only be integration tested.
If FakeHttpMessageHandler is initialized with no parameters, it will create an instance of T, serialize it as JSON and return it in a content of HttpResponse.
using(varhttpMessageHandler=newFakeHttpMessageHandler<OutputType>())using(varhttpClient=newHttpClient(httpMessageHandler)){varresponse=awaithttpClient.GetAsync("http://zheludov.com");}You may also choose to override returned object by either passing an instance of returned object to a constructor or a function that will retrieve it. In both cases an object will be serialized into JSON unless serializer is overwritten or T is string;
// Passing an instance of output objectvaroutput=newOutputType();using(varhttpMessageHandler=newFakeHttpMessageHandler<OutputType>(output))using(varhttpClient=newHttpClient(httpMessageHandler)){varresponse=awaithttpClient.GetAsync("http://zheludov.com");}// Passing a function that will retrieve output object.varoutputRetrieverMock=newMock<IResponceObjectRetriever>();outputRetrieverMock.Setup(retriever =>retriever.RetrieveResponseObject()).Returns(newFakeOutput());using(varhttpMessageHandler=newFakeHttpMessageHandler<FakeOutput>(()=>outputRetrieverMock.Object.RetrieveResponseObject()))using(varhttpClient=newHttpClient(httpMessageHandler)){varresponse=awaithttpClient.GetAsync("http://zheludov.com");}// Passing an asynchronous function that will retrieve output object.varoutputRetrieverMock=newMock<IResponceObjectRetriever>();outputRetrieverMock.Setup(retriever =>retriever.RetrieveResponseObjectAsync()).ReturnsAsync(newFakeOutput());using(varhttpMessageHandler=newFakeHttpMessageHandler<FakeOutput>(()=>outputRetrieverMock.Object.RetrieveResponseObject()))using(varhttpClient=newHttpClient(httpMessageHandler)){varresponse=awaithttpClient.GetAsync("http://zheludov.com");}Additionally you can override serializer function that is called to serilize response content.
varresponseString="zheludov.com";varserializerMock=newMock<ISerializer>();varresponseObjectRetrieverMock=newMock<IResponceObjectRetriever>();serializerMock.Setup(serializer =>serializer.Serialize(It.IsAny<object>())).Returns(responseString);varhandler=newFakeHttpMessageHandler<FakeOutput>(()=>responseObjectRetrieverMock.Object.RetrieveResponseObjectAsync(),(FakeOutputoutput)=>serializerMock.Object.Serialize(output));using(varhttpClient=newHttpClient(httpMessageHandler)){varresponse=awaithttpClient.GetAsync("http://zheludov.com");}publicclassApiClient:IDisposable{privatereadonlyHttpMessageHandler_httpMessageHandler;publicApiClient(HttpMessageHandlerhttpMessageHandler=null){_httpMessageHandler=httpMessageHandler;}publicasyncTask<string>GetResponseAsync(){using(varhttpClient=newHttpClient(_httpMessageHandler??newHttpClientHandler())){varresponse=awaithttpClient.GetAsync("http://zheludov.com");if(response.IsSuccessStatusCode){returnawaitresponse.Content.ReadAsStringAsync();}returnnull;}}publicvoidDispose(){_httpMessageHandler?.Dispose();}}[TestClass]publicclassApiClientTest{[TestMethod]publicasyncTaskApiClient_GetResponseAsync_VerifyHttpRequestIsMade(){varhttpHandler=newFakeHttpMessageHandler<string>("Response");using(varclient=newApiClient(httpHandler)){varresponse=awaitclient.GetResponseAsync();response.Should().NotBeNullOrWhiteSpace();}}}