a wandering wolf

Does a wandering wolf dreams of a wondering, sometimes programming sheep?

このエントリーをはてなブックマークに追加

MSTest のための Assert.Throws

まさか、1年以上投稿していなかったとは…。

さて、MSTest を使っていると、例外が発生したかのチェックには ExpectedExceptionAttribute ぐらいしか使えないの、不便ですよね?

不便でない方がいらっしゃいましたら、この記事は面白みがないので他の記事を探されるとよいかと思います。

ExpectedExceptionAttribute では物足りない理由

[TestMethod]
[ExpectedException(typeof(YourOriginalException))]
public void SomethingExceptionalTest()
{
    var sut = new MyTestTarget();

    // ここで例外が発生する
    sut.DoSomething();

    Assert.Fail();
}

このコードですと、 DoSomething メソッドで YourOriginalException という例外がスローされるのを期待しています。 もしそれがスローされなければ、最終行で Assert.Fail() に引っかかるという流れです。

それなりの事はできるんですが、投げられた例外についてもっと調べたいときには使い物になりません。 あくまでも、「想定する例外型がスローされるのを待ち構える」だけです。

そこで Assert.Throws ですよ

NUnit には、同じようなことをやるために Assert.Throws というメソッドが提供されています。 この Assert.Throws は期待する例外型を待ち受けるだけでなく、スローされた例外インスタンスを取得することも出来ます。

[TestMethod]
[ExpectedException(typeof(YourOriginalException))]
public void SomethingExceptionalTest()
{
    var sut = new MyTestTarget();

    // ここで例外が発生する
    var ex = Assert.Throws<YourOriginalException>(sut.DoSomething);

    // 例外インスタンスについての確認もできる
    Assert.AreEqual("だが…マヌケは見つかったようだな", ex.Message);
}

MSTest には Assert.Throws がないんですが、かゆいところに手が届かないというか、本当に最低限のアサーションだけ用意されているという感じですね。

作ってみた

無かったら作る。車輪は再発明する。必要なものは用意すればいいです。

public static class AssertExtension
{
    public static TException Throws<TException>(Action action) where TException : Exception
    {
        try
        {
            action.Invoke();
        }
        catch (TException actual)
        {
            if (typeof(TException) == actual.GetType())
            {
                return actual;
            }
            Assert.Fail("期待する例外が発生しませんでした。期待する型: {0}, 発生した例外: {1}", typeof(TException), actual);
        }
        Assert.Fail("期待する例外が発生しませんでした。期待する型: {0}", typeof(TException));
        return null;
    }
}

こんな風に使います。

[TestMethod]
[ExpectedException(typeof(YourOriginalException))]
public void SomethingExceptionalTest()
{
    var sut = new MyTestTarget();

    // ここで例外が発生する
    var ex = AssertExtension.Throws<YourOriginalException>(sut.DoSomething);

    // 例外インスタンスについての確認もできる
    Assert.AreEqual("だが…マヌケは見つかったようだな", ex.Message);
}

なお下記リンク先のように、世の中には MSTest に Assert.Throws が欲しい人は他にもいるので、やはりデフォルトあってよかったのでは…。

同志の作品: Asserting Exceptions in MSTest with Assert.Throws() - bradoncode.com