web-dev-qa-db-ja.com

C#:MSTestユニットテストで「例外が発生しなかった」ことを確認するにはどうすればよいですか?

「void」を返すこの1つのメソッドの単体テストを書いています。例外がスローされていないときにテストに合格するケースが1つあります。 C#でどのように書くのですか?

Assert.IsTrue(????)

(私の推測では、これがどのようにチェックすべきかですが、「???」には何が入りますか)

私の質問が十分に明確であることを願っています。

70
CuriousGeorge

とにかく、例外がスローされた場合、ユニットテストは失敗します。特別なアサートを行う必要はありません。

これは、アサーションのないユニットテストが表示される数少ないシナリオの1つです。例外が発生すると、テストは暗黙的に失敗します。

ただし、実際にこれについてアサーションを作成したい場合は、おそらく例外をキャッチして「例外はないはずですが、これを取得しました...」と報告できるようにするには、次のようにします。

[Test]
public void TestNoExceptionIsThrownByMethodUnderTest()
{
    var myObject = new MyObject();

    try
    {
        myObject.MethodUnderTest();
    }
    catch (Exception ex)
    {
        Assert.Fail("Expected no exception, but got: " + ex.Message);
    }
}

(上記はNUnitの例ですが、MSTestにも同じことが当てはまります)

117
Rob Levine

NUnitでは、次を使用できます。

Assert.DoesNotThrow(<expression>); 

コードが例外をスローしないことをアサートします。周囲にアサートがない場合でも例外がスローされるとテストは失敗しますが、このアプローチの価値は、テストで満たされていない期待とバグを区別できることです。カスタムメッセージを追加するオプションがあります。テスト出力に表示されます。わかりやすいテスト出力は、テストの失敗の原因となったコード内のエラーを見つけるのに役立ちます。

コードが例外をスローしないことを確認するテストを追加することは有効だと思います。たとえば、入力を検証しており、入力文字列をlongに変換する必要があるとします。文字列がnullの場合がありますが、これは受け入れられるため、文字列変換で例外がスローされないようにする必要があります。したがって、この機会を処理するコードがあり、テストを作成していない場合は、重要なロジックに関するカバレッジが欠落します。

23
Clarkeye

何かをテストしないでください does n't これは、コードが壊れないことを保証するようなものです。それは一種の暗示であり、私たちは皆、壊れない、バグのないコードを目指して努力しています。そのためのテストを書きたいですか?なぜたった1つの方法なのか?すべてのメソッドが例外をスローしないことをテストする必要はありませんか?その道をたどると、コードベースのすべてのメソッドに対して余分なダミーのアサートレステストが1つ追加されます。価値はありません。

もちろん、要件がメソッドを検証することdoes例外をキャッチする場合、それをテストします(またはそれを少し逆にします;それがキャッチするはずのものを投げないことをテストします)。

ただし、一般的なアプローチ/プラクティスはそのままです。テストされたコードの範囲外の人為的/あいまいな要件のテストを作成しないでください(そして、「動作する」または「投げない」というテストは、通常の例です)そのような-特にメソッドの責任がよく知られているシナリオでは)。

簡単に言うと、コードが何をすべきかに焦点を合わせてテストします。

11
k.m

このヘルパークラスは、MSTestで私の悩みを掻きました。たぶんそれもあなたを傷つける可能性があります。

[TestMethod]
public void ScheduleItsIneligibilityJob_HasValid_CronSchedule()
{
    // Arrange
    var factory = new StdSchedulerFactory();
    IScheduler scheduler = factory.GetScheduler();

    // Assert
    AssertEx.NoExceptionThrown<FormatException>(() =>
        // Act
        _service.ScheduleJob(scheduler)
    );
}

public sealed class AssertEx
{
    public static void NoExceptionThrown<T>(Action a) where T:Exception
    {
        try
        {
            a();
        }
        catch (T)
        {
            Assert.Fail("Expected no {0} to be thrown", typeof(T).Name);
        }
    }
}
5
JJS

一貫性を保つために、各テストの最後に_Assert.Whatever_が表示されるのが好きです。

私にとっては、これはAssert.IsTrue(true);を置くのと同じくらい簡単です

I 知っているしなかった偶然そのコードをそこに置いたので、これが意図したとおりであったことをざっと目を通すだけで十分に自信があるはずです。

_    [TestMethod]
    public void ProjectRejectsGappedVersioningByDefault() {

        var files = new List<ScriptFile>();
        files.Add(ScriptProjectTestMocks.GetVersion1to2());
        files.Add(ScriptProjectTestMocks.GetVersion3to4());

        Assert.Throws<ScriptProject.InvalidProjectFormatException>(() => {
            var sut = new ScriptProject(files);
        });

    }

    [TestMethod]
    public void ProjectAcceptsGappedVersionsExplicitly() {

        var files = new List<ScriptFile>();
        files.Add(ScriptProjectTestMocks.GetVersion1to2());
        files.Add(ScriptProjectTestMocks.GetVersion3to4());

        var sut = new ScriptProject(files, true);

        Assert.IsTrue(true);   // Assert.Pass() would be nicer... build it in if you like

    }
_
2
jleach