c# - 当等待模拟方法时,单元测试中的 NRE

标签 c# unit-testing .net-core moq autofixture

我正在尝试使用 mstest 为 .net Core 3 Web API 构建单元测试。

我也在使用:

  • 自动夹具
  • 起订量
  • AutoFixture.AutoMoq

此单元测试应返回 NotFound()没有找到啤酒时的响应。

    private IFixture _fixture;
    private BeerController _beerController;
    private Mock<IBeerService> _mockBeerService;

    [TestInitialize]
    public void Initialize()
    {
        _fixture = new Fixture().Customize(new AutoMoqCustomization());
        _mockBeerService = _fixture.Freeze<Mock<IBeerService>>();
        _beerController = _fixture.Create<BeerController>();
    }

    [TestMethod]
    public async Task WhenCallGetBeerWithoutMatchReturnNotFound404()
    {
        //Arrange
        int beerId = _fixture.Create<int>();
        _mockBeerService.Setup(x => x.GetBeer(It.IsAny<int>())).Returns((Task<Beer>)null);

        //Act
        var actionResult = await _beerController.Get(beerId);

        //Assert
        Assert.IsInstanceOfType(actionResult.Result, typeof(NotFoundResult));
    }

这就是我要测试的功能:

    [HttpGet("{beerId:int}")]
    public async Task<ActionResult<beer>> Get(int beerId)
    {
        try
        {
            var beer = await _beerService.Getbeer(beerId);
            if (beer == null) return NotFound();

            return Ok(beer);
        }
        catch (Exception)
        {
            return BadRequest();
        }
    }

但是我遇到了Object reference not set to an instance of an object.这行代码出现异常:var beer = await _biereService.Getbeer(beerId);

这是堆栈跟踪: at BeerProject.Controllers.BeerController.<Get>d__2.MoveNext() in F:\DevProjects\Repos\API_BeerProject\BeerProject\Controllers\BeerController.cs:line 29

我测试了return Ok(beer)通过这个测试:

    [TestMethod]
    public async Task WhenCallGetBeerWithMatchReturnOk200()
    {
        //Arrange
        int beerId = _fixture.Create<int>();
        var beer = _fixture.Create<Task<Beer>>();

        _mockBeerService.Setup(x => x.GetBeer(It.IsAny<int>())).Returns(beer);
        //Act
        var actionResult = await _beerController.Get(beerId);

        //Assert
        Assert.IsInstanceOfType(actionResult.Result, typeof(OkObjectResult));
    }  

并且工作正常。

所以我猜测他不喜欢.Returns((Task<Beer>)null)WhenCallGetBeerWithoutMatchReturnNotFound404()

最佳答案

在您的 Controller 中,您假设 GetBeer 返回一个非空任务,因为您无条件等待它。然后,您检查结果(啤酒),看看它是否为 null:

var beer = await _beerService.Getbeer(beerId);
if (beer == null) return NotFound();

在这一行中,您不会返回带有 null 啤酒的任务,而是返回 null 任务:

_mockBeerService.Setup(x => x.GetBeer(It.IsAny<int>())).Returns((Task<Beer>)null);

因此,等待 null 会导致 NullReferenceException

如果您想返回 null 啤酒作为任务的结果,则需要使用:

_mockBeerService.Setup(x => x.GetBeer(It.IsAny<int>())).Returns(Task.FromResult<Beer>(null));

或者甚至:

_mockBeerService.Setup(x => x.GetBeer(It.IsAny<int>())).ReturnsAsync(null);

关于c# - 当等待模拟方法时,单元测试中的 NRE,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59978097/

相关文章:

c# - 当 ListView Windows 窗体中没有项目时显示空文本

python - 如何在 pyUnit 中创建类范围的测试装置?

c++ - 如何为返回二进制数据的简单 C 函数实现单元测试?

c# - 仅在 Visual Studio 2010 中调试期间,简单的 Rx 代码在 Windows 窗体中默默失败

c# - 登录尝试失败 WCF 错误

javascript - 从默认导入开 Jest 模拟异步函数

c# - Blazor WebAssembly 更新页面标题

.net-core - 为什么 dotnet 运行启动 2 个进程?

c# - .net core 是否支持代码契约?

c# - C# 中是否有支持故障安全迭代的良好 IList 和 IDictionary 实现?