Unit Testing
It’s trivial to mock RestClient as a dependency in your unit testing, by mocking IHttpClientWrapper.
For example
//Arrange
var mockHttpClient = new Mock<IHttpClientWrapper>();
var fakeResponse = new HttpResponseMessage
{
RequestMessage = new HttpRequestMessage()
};
fakeResponse.Headers.Add("Accept", "text/html"); //change the response to suit you needs
mockHttpClient
.Setup(_ => _.Send(HttpMethod.Get, It.IsAny<Uri>(), It.IsAny<IDictionary<string, string>>(), It.IsAny<object>()))
.Returns(Task.FromResult(fakeResponse));
dynamic client = new RestClient(mockHttpClient.Object, "http://test.test");
//Act
var result = await client.Get();
//Assert
Assert.AreEqual("text/html", result.HttpResponseMessage.Headers.GetValues("Accept")[0]);
However read on as it’s even easier, less code and more flexible to use the UnitTestHandler.
UnitTestHandler
You can use the UnitTestHandler to fake/mock, pretty much anything in RestClient. The UnitTestHandler works in a similar way to the UseHandler() pipeline extension, which can be used to return a fake response for a request.
UnitTestHandler like UseHandler()
takes either a Action<HttpRequestMessage>
or Func<HttpRequestMessage, HttpResponseMessage>
as a parameter, which will be invoked by RestClient when returning it’s response.
However unlike UseHandler()
UnitTestHandler by design clones the usually disposed HttpRequestMessage
or HttpResponseMessage
allowing you to easily Assert anything about the request or response in your tests.
To use it simply add it to your Config for example
dynamic client = new RestClient("http://test.com", new Config(new UnitTestHandler(request =>
{
var response = new HttpResponseMessage();
if (request.Headers.Accept.FirstOrDefault()?.MediaType == "application/json")
return new HttpResponseMessage
{
Content = new StringContent("{'foo':'bar'}")
};
return response;
})));
var result = await client.whatever.Get();
Assert.AreEqual("{'foo':'bar'}", result.ToString());
You can also use the UseUnitTestHandler()
extension method
var pipeline = new Config()
.UseUnitTestHandler(request =>
{
var response = new HttpResponseMessage();
if (request.Headers.Accept.FirstOrDefault()?.MediaType == "application/json")
return new HttpResponseMessage
{
Content = new StringContent("{'foo':'bar'}")
};
return response;
});
dynamic client = new RestClient("http://test.com", pipeline);
var result = await client.whatever.Get();
Assert.AreEqual("{'foo':'bar'}", result.ToString());
Chaining using the UseUnitTestHandler()
extension method will simplify your code.
var pipeline = new Config()
.UseUnitTestHandler(request =>
{
var response = new HttpResponseMessage();
if (request.Headers.Accept.FirstOrDefault()?.MediaType == "application/json")
return new HttpResponseMessage
{
Content = new StringContent("{'foo':'bar'}")
};
return response;
})
.UseUnitTestHandler(request =>
{
var response = new HttpResponseMessage();
if (request.Headers.Accept.FirstOrDefault()?.MediaType == "text/html")
return new HttpResponseMessage
{
Content = new StringContent("<foo /><bar />")
};
return response;
});
dynamic client = new RestClient("http://test.com", pipeline);
var jsonResult = await client.whatever.Get();
var htmlResult = await client
.Headers(new Dictionary<string, string> { { "Content-Type", FormUrlEncodedContentType } })
.whatever
.Get();
Assert.AreEqual("{'foo':'bar'}", jsonResult.ToString());
Assert.AreEqual("<foo /><bar />", htmlResult.ToString());
When using IHttpClientFactory use the UseUnitTestHandler extension method when adding the RestClient to your .NET Core DI container (usually in Startup.cs):
services
.AddRestClient("http://headers.jsontest.com/")
.UseUnitTestHandler(request =>
{
var response = new HttpResponseMessage();
if (request.Headers.Accept.FirstOrDefault()?.MediaType == "application/json")
return new HttpResponseMessage
{
Content = new StringContent("{'foo':'bar'}")
};
return response;
});
dynamic _restClientFactory.CreateClient(); //_restClientFactory is the injected IHttpRestClientFactory;
var result = await client.whatever.Get();
Assert.AreEqual("{'foo':'bar'}", result.ToString());