かずきのBlog@hatena

日本マイクロソフトに勤めています。XAML + C#の組み合わせをメインに、たまにASP.NETやJavaなどの.NET系以外のことも書いています。掲載内容は個人の見解であり、所属する企業を代表するものではありません。

async awaitを使ったテストの単体テスト

Windows ストア アプリではasync awaitを使った非同期なメソッドを結構作ることになると思います。そんなメソッドの単体テストのやりかたの紹介です。
今回のテスト対象は、非同期にする意味が全くないですが足し算を行う以下のクラスです。

using System.Threading.Tasks;

namespace App7
{
    public class Calc
    {
        public async Task<int> Add(int x, int y)
        {
            await Task.Delay(1000);
            return x + y;
        }
    }
}

同じソリューションに単体テストライブラリのプロジェクトを作って、そこにApp7プロジェクトを参照設定してCalcクラスを使えるようにします。Express版には単体テストを作成するテンプレートが入ってないので、自分でせっせと以下のようなコードを書きます。

using App7;
using Microsoft.VisualStudio.TestPlatform.UnitTestFramework;
using System.Threading.Tasks;

namespace UnitTestLibrary1
{
    [TestClass]
    public class CalcTest
    {
        [TestMethod]
        public async Task AddTest()
        {
            var calc = new Calc();
            var answer = await calc.Add(10, 20);
            Assert.AreEqual(30, answer);
        }
    }
}

ポイントはTestMethodアトリビュートをつけているメソッドもasync修飾子をつけるようにしてTaskを戻り値にすることです。
あとは、普通にテストメソッド内でawaitして結果を受け取ってAssertしてやりましょう。

テストプロジェクトを選択した状態でメニューの[テスト]→[実行]→[すべてのテスト]をやるとビルドが実行されテストが実行されます。そしてテストエクスプローラに以下のように結果が表示されます。

いやいや、非同期メソッド素通りしてるだけじゃないの?と最初は思ったんですが、ちゃんとAssert変えてやるとテスト失敗もするしちゃんと実行できてるみたいです。

using App7;
using Microsoft.VisualStudio.TestPlatform.UnitTestFramework;
using System.Threading.Tasks;

namespace UnitTestLibrary1
{
    [TestClass]
    public class CalcTest
    {
        [TestMethod]
        public async Task AddTest()
        {
            var calc = new Calc();
            var answer = await calc.Add(10, 20);
            // わざと失敗してみる
            Assert.AreEqual(999999, answer);
        }
    }
}

うん、いいね!