创建客户端时,模拟的HttpClientFactory返回null

时间:2020-05-15 15:15:55

标签: c# unit-testing nunit asp.net-core-3.1 nsubstitute

我正在尝试对将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);
}

1 个答案:

答案 0 :(得分:3)

被测对象方法

 var client = _httpClientFactory.CreateClient("Movie Api");

但是您将模拟配置为在调用CreateClient()时返回。

httpClientFactoryMock.CreateClient().Returns(fakeHttpClient);

这意味着在测试和调用CreateClient("Movie Api")时,模拟程序不会知道该怎么做,因此会返回 null ,从而导致下一个调用抛出NRE

将模拟程序设置为在调用被测系统时的行为符合预期。

//...

httpClientFactoryMock.CreateClient("Movie Api").Returns(fakeHttpClient);

//...