异步unit testing中的Stubbing Task返回方法
假设我有以下类和它依赖的接口:
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(); }
当我对这个方法进行unit testing时,我可以执行以下操作(使用xUnit和Rhino Mocks):
[Fact] public async Task MyTest() { IRepository repositoryStub = MockRepository.GenerateStub(); MyController controller = new MyController(repositoryStub); await controller.MethodUnderTest(1); }
这与System.NullReferenceException失败:对象引用未设置为对象的实例 。
使用以下StackTrace:
UnitTest.MyController.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生成的statemachine在null
上调用MoveNext()
?
我可以通过以下方式解决这个问题:
repositoryStub.Expect(r => r.Commit()).Return(Task.FromResult(true);
但这感觉有点奇怪..我可以使用任何T
for FromResult
并且测试将运行。 我找不到将返回非genericsTask
的FromResult
方法。
我用于T
是否重要? 或者我应该以其他方式解决这个问题?
你需要归还一些东西; async Task
方法不能返回null
。
T
没关系。 您可以声明一个static readonly Task SuccessTask = Task.FromResult
如果你想要作为助手常数。 我的AsyncEx库中有类似的常量 。
如果您的目标是.NET Framework 4.6或更高版本,那么现在可以使用.Returns(Task.CompletedTask)
而不是更短。