使用 NUnit、NSubstitute 和异步方法进行单元测试时出现 NullReferenceException

NullReferenceException in unittesting with NUnit, NSubstitute, and async method

我正在使用 NUnit 和 NSubstitute 在 C# 中进行一些单元测试。我有一个名为 Adapter 的 class,它有一个方法 GetTemplates(),我想进行单元测试。 GetTemplates() 使用 httpclient,我使用接口模拟了它。

GetTemplates 中的调用类似于:

public async Task<List<Template>> GetTemplates()
{
    //Code left out for simplificity. 

    var response = await _client.GetAsync($"GetTemplates");

    if (!response.IsSuccessStatusCode)
    { 
        throw new Exception();
    }

}

我想 _client.GetAsync 到 return 一个 HttpResponseMessage 和一个 HttpStatusCode.BadRequest 以便我可以测试是否抛出异常。

测试方法如下:

[Test]
public void GetTemplate_ReturnBadRequestHttpMessage_ThrowException()
{
     //Arrange.
     var httpMessage = new HttpResponseMessage(HttpStatusCode.BadRequest);
     _client.GetAsync("").Returns(Task.FromResult(httpMessage));

     //Act.
     var ex = Assert.ThrowsAsync<Exception>(async () => await _Adapter.GetSigningTemplates());

     //Assert.
     Assert.IsInstanceOf<Exception>(ex);
 }

当方法有运行时,它returns

System.NullReferenceException: Object reference not set to an instance of an object.

我做错了什么?

这是因为模拟客户端的排列与测试时实际调用的不匹配。

客户期望

var response = await _client.GetAsync($"GetTemplates");

但此设置适用于

 _client.GetAsync("")

注意传递的不同参数。当 mocks 没有得到确切的设置时,它们通常 return 其 return 类型的默认值,在这种情况下是 null.

更改测试以使用预期参数

_client.GetAsync($"GetTemplates").Returns(Task.FromResult(httpMessage));

引用Return for specific args

或使用参数匹配器

_client.GetAsync(Arg.Any<string>()).Returns(Task.FromResult(httpMessage));

引用Argument matchers