首页 > 解决方案 > XUnit + Moq + FluentAssertions,在 Task 上检查 null 而不是正确的对象

问题描述

我是单元测试和起订量的新手。

使用 Postman 测试 DeleteItemAsync(),

    [HttpDelete("{id:length(24)}")]
    public async Task<IActionResult> DeleteItemAsync(string id)
    {
        var item = _ItemRepo.GetItemByIdAsync(id);
        if (item == null)
            return NotFound();
        await _itemRepo.DeleteItemAsync(id);
        return NoContent();
    }

当找不到该项目时,我会得到正确的结果 NotFound。

运行我的单元测试时它失败了,因为在控制器中,它正在检查由 moq _repoStub 调用 GetItemByIdAsync(id) 返回的 Task 对象是否为空。

    [Fact]
    public async Task DeleteItemAsync_ItemDoesntExist_ReturnsNotFound()
    {
        // Arrange
        _repoStub
            .Setup(repo => repo.GetItemByIdAsync(It.IsAny<String>()))
            .ReturnsAsync((Item)null);
        _repoStub
            .SetupSequence(repo => repo.DeleteItemAsync(It.IsAny<String>()))
            .Returns(Task.FromResult<NotFoundResult>(null));

        var controller = new ItemController(_repoStub.Object, _mapperStub);

        // Act
        var actionResult = await controller.DeleteItemAsync(It.IsAny<String>());

        // Assert
        actionResult.Should().BeOfType<NotFoundResult>();
    }

标签: c#unit-testingmoqxunit

解决方案


GetItemByIdAsync应在待测对象中等待

[HttpDelete("{id:length(24)}")]
public async Task<IActionResult> DeleteItemAsync(string id)
{
    var item =  await _ItemRepo.GetItemByIdAsync(id); //<--!!!
    if (item == null)
        return NotFound();
    await _itemRepo.DeleteItemAsync(id);
    return NoContent();
}

否则它将返回 a Task,因此不会null如您的错误所示。

另外,请注意,它It.IsAny应该只用在期望表达式中,而不是作为变量

[Fact]
public async Task DeleteItemAsync_ItemDoesntExist_ReturnsNotFound()
{
    // Arrange
    _repoStub
        .Setup(repo => repo.GetItemByIdAsync(It.IsAny<String>()))
        .ReturnsAsync((Item)null);
    _repoStub
        .SetupSequence(repo => repo.DeleteItemAsync(It.IsAny<String>()))
        .Returns(Task.FromResult<NotFoundResult>(null));

    var controller = new ItemController(_repoStub.Object, _mapperStub);

    // Act
    var actionResult = await controller.DeleteItemAsync(""); //<--It.IsAny<String>() removed

    // Assert
    actionResult.Should().BeOfType<NotFoundResult>();
}

推荐阅读