【问题标题】:Mocked HttpClientFactory returns null when creating client创建客户端时,模拟的 HttpClientFactory 返回 null
【发布时间】:2020-09-01 11:25:20
【问题描述】:

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

【问题讨论】:

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


    【解决方案1】:

    被测对象方法调用

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

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

    httpClientFactoryMock.CreateClient().Returns(fakeHttpClient);
    

    这意味着当测试和CreateClient("Movie Api")被调用时,mock不知道该做什么,因此返回null,导致下一次调用抛出NRE

    将模拟设置为在调用被测系统时按预期运行。

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-07-02
      • 2020-09-13
      • 2019-11-25
      • 2011-06-16
      • 1970-01-01
      • 2021-12-12
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多