27

假设我有以下类和它依赖的接口:

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 和 Rhino Mocks):

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

    MyController controller = new MyController(repositoryStub);

    await controller.MethodUnderTest(1);
}

这将失败并出现System.NullReferenceException:未将对象引用设置为对象的实例

使用以下 StackTrace:

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

发生此错误是否正确,因为为 async/await 调用生成的Commit()返回和状态机调用a ?nullMoveNext()null

我可以通过执行以下操作来解决此问题:

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

但这感觉有点奇怪..我可以使用任何TforFromResult<T>并且测试将运行。我找不到FromResult会返回非泛型的方法Task

我用什么重要T吗?还是我应该以其他方式解决这个问题?

4

2 回答 2

47

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

T没关系。如果需要,可以将 a 声明static readonly Task SuccessTask = Task.FromResult<object>(null);为辅助常量。我的 AsyncEx 库中有类似的常量

于 2012-12-21T16:29:38.273 回答
6

如果您的目标是 .NET Framework 4.6 或更高版本,您现在可以.Returns(Task.CompletedTask)改用稍短一些的版本。

于 2017-07-04T10:06:37.990 回答