Unit Testing
Unit testing code that uses RestClient is trivial - use the UnitTestHandler to fake responses without hitting the network, and the Verify method from DalSoft.RestClient.Testing to assert the results fluently.
[Fact]
public async Task GetUser_ProvidingAValidUserId_ReturnsExpectedUser()
{
var client = new RestClient("http://test.com", new Config()
.UseUnitTestHandler(request => new HttpResponseMessage
{
Content = new StringContent("{ \"id\": 1, \"username\": \"Bret\" }")
}));
await client.Resource("users/1").Get()
.Verify<HttpResponseMessage>(response => response.IsSuccessStatusCode)
.Verify<User>(user => user.Username == "Bret");
}
The UnitTestHandler can fake/mock pretty much anything in RestClient - including asserting anything about the request. See UnitTestHandler for detailed info on the handler.
Mocking a RestClient dependency
The simplest mock is no mock at all - because RestClient’s behaviour comes from the pipeline, a real RestClient configured with the UnitTestHandler is the fake. How you hand it to the code under test depends on what that code takes:
A typed client or anything taking IRestClient - pass it a RestClient with faked responses:
var gitHubClient = new GitHubClient(new RestClient("http://test.com", new Config()
.UseUnitTestHandler(request => new HttpResponseMessage
{
Content = new StringContent("[{ \"name\": \"DalSoft.RestClient\" }]")
})));
var repositories = await gitHubClient.GetRepositories("dalsoft");
Assert.Equal("DalSoft.RestClient", repositories.Single().Name);
Code taking IRestClientFactory (see IHttpClientFactory) - provide a factory returning that RestClient, handy for unit tests and for overriding services in e2e tests:
public class MockRestClientFactory : IRestClientFactory
{
public RestClient CreateClient()
{
return new RestClient
(
"http://NotUsedAsMockResponseReturned",
new Config()
.UseUnitTestHandler(request => new HttpResponseMessage
{
Content = new StringContent("[{ \"name\": \"Hello World\" }]")
})
);
}
public RestClient CreateClient(string name)
{
return CreateClient();
}
}
Code taking IHttpClientWrapper - if you’d rather mock at the transport level, RestClient has a constructor taking IHttpClientWrapper (its one method Send returns the HttpResponseMessage). You get the same result as the UnitTestHandler with more setup, so prefer the handler unless you have a reason not to:
var mockHttpClient = new Mock<IHttpClientWrapper>();
mockHttpClient
.Setup(_ => _.Send(HttpMethod.Get, It.IsAny<Uri>(), It.IsAny<IDictionary<string, string>>(), It.IsAny<object>()))
.Returns(Task.FromResult(new HttpResponseMessage { RequestMessage = new HttpRequestMessage() }));
dynamic client = new RestClient(mockHttpClient.Object, "http://test.test");