Reputation: 89
I am trying to unit test a service that uses the IHttpClientFactory
with Nunit and NSubstitute for mocking.
The service I want to test looks like this
public class Movies : IMovies
{
private readonly IHttpClientFactory _httpClientFactory;
public Movies(IHttpClientFactory httpClientFactory)
{
_httpClientFactory = httpClientFactory;
}
public async Task<MovieCollection> GetPopularMovies(int PageNumber = 1)
{
// Get an instance of HttpClient from the factpry that we registered
// in Startup.cs
var client = _httpClientFactory.CreateClient("Movie Api");
// Call the API & wait for response.
// If the API call fails, call it again according to the re-try policy
// specified in Startup.cs
var result =
await client.GetAsync($"movie/popular?api_key=<the_api_key>language=en-US&page={PageNumber}");
if (result.IsSuccessStatusCode)
{
// Read all of the response and deserialise it into an instace of
var content = await result.Content.ReadAsStringAsync();
return JsonConvert.DeserializeObject<MovieCollection>(content);
}
return null;
}
}
When I run the test I get an error that says
System.NullReferenceException : Object reference not set to an instance of an object. at MovieApi.Services.Movies.GetPopularMovies(Int...
Here is the test I am running.The error occurs only when I put the keyword await
in the line
var result = await service.GetPopularMovies(1);
Check the Test code below:
[Test]
public async Task GetPopular_WhenCalled_ReturnOK()
{
//arrange
var moviecollection = new MovieCollection();
var httpClientFactoryMock = Substitute.For<IHttpClientFactory>();
var fakeHttpMessageHandler = new FakeHttpMessageHandler(new HttpResponseMessage() {
StatusCode = HttpStatusCode.OK,
Content = new StringContent(JsonConvert.SerializeObject(moviecollection), Encoding.UTF8, "application/json")
});
var fakeHttpClient = new HttpClient(fakeHttpMessageHandler);
httpClientFactoryMock.CreateClient().Returns(fakeHttpClient);
// Act
var service = new Movies(httpClientFactoryMock);
var result = await service.GetPopularMovies(1);
//assert
Assert.IsNotNull(result);
}
Upvotes: 0
Views: 3669
Reputation: 246998
The subject method under test calls
var client = _httpClientFactory.CreateClient("Movie Api");
but you configure the mock to return when CreateClient()
is invoked.
httpClientFactoryMock.CreateClient().Returns(fakeHttpClient);
which means that when testing and CreateClient("Movie Api")
is invoked the mock wont know what to do and thus returns null, causing the next call to throw NRE
Setup the mock to behave as expected when the system under test is invoked.
//...
httpClientFactoryMock.CreateClient("Movie Api").Returns(fakeHttpClient);
//...
Upvotes: 4