2

Visual Studio 2012で最新バージョンのNUnit(2.6.2)を使用しており、resharperとVisualStudioテストランナーの両方を使用しています。次のサンプルテストがあり、予期された非同期メソッド呼び出しで例外が発生することを確認しようとしています。

残念ながら、これは期待どおりに機能していないようです。最初のテストAsyncTaskCanceledSemiWorkingは、expectedexception属性があるためにのみ機能します。実際のアサートは完全に無視されます(失敗するための偽物であるArgumentOutOfRange例外からわかるように)。

正常にAsyncTaskCanceledWorking動作しますが、例外が指定された行にスローされることをテストしないため、あまり役に立ちません。

3番目は以下で堂々と失敗します...。

System.Threading.Tasks.TaskCanceledException : A task was canceled.
Exception doesn't have a stacktrace

特定の行からTaskCanceledExceptionをテストする方法についてのアイデアは非常に役立ちます。

ありがとう

    [Test]
    [ExpectedException(typeof(TaskCanceledException))]
    public async Task AsyncTaskCanceledSemiWorking()
    {
        CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();
        CancellationToken token = cancellationTokenSource.Token;

        cancellationTokenSource.Cancel();

        Assert.That(await LongRunningFunction(token), Throws.InstanceOf<ArgumentOutOfRangeException>());


    }

    [Test]
    [ExpectedException(typeof(TaskCanceledException))]
    public async Task AsyncTaskCanceledWorking()
    {
        CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();
        CancellationToken token = cancellationTokenSource.Token;

        cancellationTokenSource.Cancel();

        int i = await LongRunningFunction(token);
    } 


    [Test]
    public async Task AsyncTaskCanceledFailed()
    {
        CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();
        CancellationToken token = cancellationTokenSource.Token;

        cancellationTokenSource.Cancel();

        Assert.That(await LongRunningFunction(token), Throws.InstanceOf<TaskCanceledException>());

    }

    public async Task<int> LongRunningFunction(CancellationToken token)
    {
        token.ThrowIfCancellationRequested();

        await Task.Delay(1000, token);

        return 5;
    } 
4

3 に答える 3

10

LongRunningFunctionをスローすることを確認したいと思いますTaskCanceledException

あなたが経験している行動は完全に正しいと思います。誤解は次のステートメントにあります。

await LongRunningFunction(token)

ここでは、非同期操作を効果的に実行し、完了するのを待っています。これにより、呼び出しで発生した最初の例外も再スローされます。基本的にそれを次のものに置き換えることができます:

throw new TaskCanceledException()

したがって、最初の 2 つのテストが成功している理由 - を使用しているExpectedExceptionAttribute- と 3 番目のテストが失敗している - は、例外を予期していません。

の最初の引数はAssert.That、後で を使用する場合Throws、何らかのデリゲートにする必要があります。これは、NUnit がその呼び出しから発生する例外をキャッチするために呼び出す必要があるためです。自分で呼び出す場合、NUnit が例外をトラップする方法はもちろんありませんExpectedExceptionAttribute

つまり、理想的には正しい方法は次のとおりです。

// WARNING: this code does not work in NUnit <= 2.6.2
Assert.That(async () => await LongRunningFunction(token), Throws.InstanceOf<TaskCanceledException>());

NUnit は非同期メソッドのこの構文をサポートしていることをお伝えしたいと思います。これは非常に自然で、コードの特定の部分で例外をテストすることができますが、そうではなく、テストは失敗したことを報告します。例外を予期していましたが、例外は発生しませんでした。

その理由は、その非同期匿名メソッドの呼び出しから例外を取得するために、NUnit がそれを待機する必要があるためです。現在は待機していません。

私があなたに与えることができる1つの代替案は、非同期操作によって返されたタスクで非非同期ラムダを使用することですが、非同期操作を待機することは、タスクを待機することとは異なる方法で動作するWaitため、残念ながら構文はそれほど良くありません戻り値。具体的には、非同期操作からスローされた例外の場合、最初のケースで実際の例外を取得し、2 番目のケースで例外を取得します。いずれにしても、2.6.2 で動作するコードは次のとおりです。AggregateException

var aggregate = Assert.Throws<AggregateException>(() => LongRunningFunction(token).Wait());
Assert.IsInstanceOf<TaskCanceledException>(aggregate.InnerExceptions.Single());

結論として、NUnit 2.6.2 では実際に非同期テスト メソッドのサポートが導入され、async [void|Task|Task<T>]テストを記述できるようになりましたが、この種のアサーションで役立つ非同期匿名メソッドのサポートを拡張することは検討していませんでした。できる。

于 2012-10-24T21:31:17.607 に答える
0

Resharper 7.1 以降を NUnit 2.6.2 以降で使用すると、テスト メソッドpublic async voidが機能します。Resharper 7.1 が本日リリースされました (2012 年 11 月 13 日)

Resharper テスト ランナーの以前のバージョンは、テストが完了するのを待たず、実際に何もテストせずに合格することができます。

2.6.2 より前のバージョンの NUnit には、ほとんど同じ問題がありました。

Resharper NUnit テスト ランナーは、NUnit GUI およびコマンドライン テスト ランナーと同じコードベースではなく、Jetbrains によって個別に更新されます。

于 2012-11-13T21:53:32.260 に答える
-2

Peter 残念ながら、これは期待どおりに機能していないようです。最初のテスト AsyncTaskCanceledSemiWorking は、expectedexception 属性があるためのみ機能します。実際の assert は完全に無視されます (ArgumentOutOfRange 例外でわかるように、失敗させるための単なる偽物です)。

属性が Assert.Throws よりも優先されるため、期待は間違っています。

シモーネが示したように、例外が InstanceOf であることを「アサート」することが期待されるため、スローではなくアサーションに属します。あなたの期待は、おそらく Java でのスローの使用方法に基づいていると思います。

于 2012-10-25T09:36:06.300 に答える