在UnitTest中使用NullReferenceException在异步方法上使用Verifyable

时间:2018-12-21 10:10:12

标签: c# unit-testing exception moq xunit

我只是在使用xUnitMoq设置单元测试时遇到了问题。

我的受训者

方法TestMethod()包含我要测试的逻辑。它是异步的,尽管返回Task

public class Testee
{
    private readonly IDoSomething _doSomething;

    public Testee(IDoSomething doSomething)
    {
        _doSomething = doSomething;
    }

    public async Task TestMethod()
    {
        await _doSomething.DoAsync(true); // throws NullReferenceException in Unit-Test
    }
}

界面IDoSomething如下

public interface IDoSomething
{
    Task DoAsync(bool aboolean);
}

单元测试

现在我可以像这样设置我的单元测试。

public class TesteeTest
{
    [Fact]
    public async Task MyTest()
    {
        var mock = new Mock<IDoSomething>();
        mock.Setup(x => x.DoAsync(It.IsAny<bool>())).Verifiable();

        var testee = new Testee(mock.Object);

        await testee.TestMethod(); // Test breaks here because it throws an exception

        mock.Verify(x => x.DoAsync(true), Times.Once);
        mock.Verify(x => x.DoAsync(false), Times.Never);
    }
}

为什么会出现此异常?

1 个答案:

答案 0 :(得分:3)

mock.Setup()缺少返回值,并返回null。因此,在TestMethod()中,Task返回的_doSomething.DoAsync(true)nullnull等待着,当然会导致System.NullReferneceException

要解决此问题,建议您将.Returns(Task.CompletedTask)添加到Mock-Setup中。

mock.Setup(x => x.DoAsync(It.IsAny<bool>())).Returns(Task.CompletedTask).Verifiable();

随着await使用Awaiter-Pattern进行编译,现在有一个任务可以调用.GetAwaiter(),以返回TaskAwaiter。这些原则在这里有更好的解释: