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()リターンとステートマシンが?nullMoveNext()null

私はこれを次のようなことで修正できます:

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

しかし、これは少し奇妙に感じます。私は任意TのforFromResult<T>を使用でき、テストが実行されます。FromResult非ジェネリックを返すメソッドが見つかりませんTask

私が何に使うかは重要Tですか?または、これを別の方法で修正する必要がありますか?

4

2 に答える 2

47

何かを返す必要があります。async Taskメソッドは決して返すことはできませんnull

T関係ありません。static readonly Task SuccessTask = Task.FromResult<object>(null);必要に応じて、をヘルパー定数として宣言できます。AsyncExライブラリにも同様の定数があります。

于 2012-12-21T16:29:38.273 に答える