次のクラスとそれに依存するインターフェースがあるとしましょう。
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()
リターンとステートマシンが?null
MoveNext()
null
私はこれを次のようなことで修正できます:
repositoryStub.Expect(r => r.Commit()).Return(Task.FromResult<bool>(true);
しかし、これは少し奇妙に感じます。私は任意T
のforFromResult<T>
を使用でき、テストが実行されます。FromResult
非ジェネリックを返すメソッドが見つかりませんTask
。
私が何に使うかは重要T
ですか?または、これを別の方法で修正する必要がありますか?