异步单元测试中的任务返回方法

本文关键字:返回 方法 任务 单元测试 异步 | 更新日期: 2023-09-27 17:49:24

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

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 mock):

[Fact]
public async Task MyTest()
{
    IRepository repositoryStub = MockRepository.GenerateStub<IRepository>();
    MyController controller = new MyController(repositoryStub);
    await controller.MethodUnderTest(1);
}

这在系统中失败。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

这个错误是否正确,因为Commit()返回null,并且为async/await生成的状态机在null上调用MoveNext() ?

我可以这样做:

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

但这感觉有点奇怪…我可以为FromResult<T>使用任何T,测试将运行。我找不到一个会返回非通用TaskFromResult方法。

我用什么T重要吗?还是我该用别的办法解决?

异步单元测试中的任务返回方法

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

T不重要。如果需要,可以将static readonly Task SuccessTask = Task.FromResult<object>(null);声明为helper常量。我有类似的常量在我的AsyncEx库。

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