存根任务在异步单元测试方法返回(Stubbing Task returning method in

2019-07-17 11:34发布

比方说,我有以下的类,它依赖于一个接口:

public class MyController
{
    private IRepository _repository;
    public MyController(IRepository repository)
    {
        _repository = repository;
    }

    public async Task MethodUnderTest(int someId)
    {
        var o = await _repository.FindById(someId);
        // update o
        await _repository.Commit();
    }
}

public interface IRepository
{
    Task Commit();
}

当我单元测试该方法我可以将以下(使用的xUnit和犀牛制品)做:

[Fact]
public async Task MyTest()
{
    IRepository repositoryStub = MockRepository.GenerateStub<IRepository>();

    MyController controller = new MyController(repositoryStub);

    await controller.MethodUnderTest(1);
}

这个失败,System.NullReferenceException:对象不设置为一个对象的一个实例

用下面的堆栈跟踪:

UnitTest.MyController.<MethodUnderTest>d__0.MoveNext() in 
\UnitTest\Class1.cs:line 35
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
   at \UnitTest\Class1.cs:line 20

它是正确的,因为出现这种错误Commit()返回null和产生的statemachine异步/的await调用MoveNext()上的null

我可以做这样的事情解决这个问题:

repositoryStub.Expect(r => r.Commit()).Return(Task.FromResult<bool>(true);

但是,这感觉有点怪怪的。我可以使用任何TFromResult<T>和测试运行。 我无法找到一个FromResult方法会返回一个非一般的Task

不要紧,我用的T ? 或者我应该解决这个问题一些其他的方式?

Answer 1:

您将需要返回的东西; async Task的方法永远不能返回null

T无所谓。 你可以声明一个static readonly Task SuccessTask = Task.FromResult<object>(null); 作为帮助不变,如果你想要的。 我有类似的常量在我AsyncEx库。



Answer 2:

如果你的目标的.NET Framework 4.6或更高版本,您现在可以使用.Returns(Task.CompletedTask)而不是它略短。



文章来源: Stubbing Task returning method in async unit test