async/awaitのテスト方法
C# 5で導入されたasync/awaitキーワードにより、Task
クラスを使った非同期メソッド(以降、「asyncメソッド」と呼びます)の記述が簡潔に書けるようになりました。
public class AsyncSample { public static async Task<string> SampleMethodAsync() { await Task.Run(() => Thread.Sleep(3000)); return "非同期実行完了!"; } }
このコードは、3秒ほど掛かる処理(実態はSleep()
)を非同期で実行します。処理が完了すると、"非同期実行完了!"という文字列を返します。
新しいMSTestでの書き方
このように記述するasyncメソッドのテストには、VS2010のMSTestでは次のように書いていました。
[TestMethod()] public void SampleMethodAsyncTest_MSTest_従来の書き方() { var task = AsyncSample.SampleMethodAsync(); // 返値のTask<string>を受け取って… task.Wait(); // 非同期実行が終わるまで、待機する。 var result = task.Result; // 非同期実行の結果を取りだし Assert.AreEqual<string>("非同期実行完了???", result); // このテストは、予想通り RED になる。 // テストの実行時間も、予想通り3秒ほど掛かる。 }
これを、VS11betaのMSTestでは次のようにasync/awaitを使って簡潔に記述できます。ポイントは、テストメソッドの返値をTask
クラスにすることです。
[TestMethod()] public async Task SampleMethodAsyncTest_MSTest_正しい書き方() // 返す型が Task { var result = await AsyncSample.SampleMethodAsync(); Assert.AreEqual<string>("非同期実行完了???", result); // このテストは、予想通り RED になる。 // テストの実行時間も、予想通り3秒ほど掛かる。 }
ここで、メソッドの型をTask
ではなく従来通りにvoid
と書いてしまうと、MSTestのテストランナーは非同期の完了を待ちません。そのためawait
後のAssert
が実行されず、すべてのテストがGREEN(成功)になってしまいます(下の画像中のSampleMethodAsyncTest_MSTest_間違い()
)。なお、必ず一度RED(失敗)を確認してから実装に手を加えてGREENにする、というテストファーストの習慣を守っていれば、そのようなミスも防ぐことができます。
NUnitでの書き方
NUnitでは従来通りに記述します。ただし、.NET 4.5で追加された機能を使って、少し簡潔に書けるようになりました。
[TestCase()] public void SampleMethodAsyncTest_NUnit_正しい書き方1() { var result = AsyncSample.SampleMethodAsync().GetAwaiter().GetResult(); // .GetAwaiter().GetResult() で、非同期実行の完了を待つ。 // この場合、非同期実行中の例外はそのまま送り出されてくる。 Assert.AreEqual("非同期実行完了???", result); // このテストは、予想通り RED になる。 // テストの実行時間も、予想通り3秒ほど掛かる。 }