我正在尝试对将IHttpClientFactory
与Nunit和NSubstitute结合使用的服务进行单元测试。
我要测试的服务如下
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;
}
}
运行测试时,我看到一条错误消息
System.NullReferenceException:对象引用未设置为对象的实例。 在MovieApi.Services.Movies.GetPopularMovies(Int ...
这是我正在运行的测试。仅当我在行中放入关键字await
时才会发生错误
var result = await service.GetPopularMovies(1);
检查下面的测试代码:
[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);
}
答案 0 :(得分:3)
被测对象方法
var client = _httpClientFactory.CreateClient("Movie Api");
但是您将模拟配置为在调用CreateClient()
时返回。
httpClientFactoryMock.CreateClient().Returns(fakeHttpClient);
这意味着在测试和调用CreateClient("Movie Api")
时,模拟程序不会知道该怎么做,因此会返回 null ,从而导致下一个调用抛出NRE
将模拟程序设置为在调用被测系统时的行为符合预期。
//...
httpClientFactoryMock.CreateClient("Movie Api").Returns(fakeHttpClient);
//...