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


88

「void」を返すこの1つのメソッドの単体テストを書いています。例外が発生しない場合にテストに合格するケースを1つ挙げたいと思います。C#でそれを書くにはどうすればよいですか?

Assert.IsTrue(????)

(私の推測では、これは私がチェックする方法ですが、「???」には何が入りますか)

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


MSTestまたはNUnitを使用していますか?
マットグランデ

2
MSTestでは、キャッチされなかった例外により、テストが自動的に失敗します。キャッチされた例外を説明しようとしていますか?
フィル

「try-catchforC#」を検索すると、スローされた例外とスローされなかった例外を処理する方法がわかります。
Foggzie 2012

1
NUnitの場合は、Assert.That(lambda).Throws.Nothingを調べます(最近変更されたと思いますが)
Matt Grande

回答:


138

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

これは、アサーションがまったくない単体テストが表示される数少ないシナリオの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についても同じことが言えます)


明らかに、これが当てはまるために、そのような例外を見つけに行くべきではありません。
Servy 2012

7
キャッチされない例外がスローされた場合にのみ、テストは失敗します。例外ハンドラー内のコードによっては、単体テストに合格する場合があります。
ediblecode 2012

1
これはMsUnittestに役立つため、UnittestにはAssert.DoesNotThrow(()メソッドはありません。
BaşarKaya 2018

25

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

Assert.DoesNotThrow(<expression>); 

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

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


1
明示的なDoesNotThrowは素晴らしいです。テストでAssert。*を見ることに慣れている場合は、他の人が怠惰で忘れていたと思うかもしれません。
マットベックマン2014年

vstestまたはmstestに同等のものはありますか?
Dan Csharpster 2015年

1
@DanCsharpster、少なくともMSTestにはないと思います-過去にMSTestでこの機能が必要だったとき、私は次のようなことをしました: public class TestBase { //believe me, I don't like this anymore than you do. protected void AssertDoesNotThrow(Action action, string message) { try { action(); } catch (Exception) { Assert.Fail(message); } } }
Clarkeye 2015年

@Clarkeye、それは興味深いアイデアです。ありがとう!うまくいけば、彼らは将来のバージョンで、NUnitをより良くコピーすることを学ぶでしょう。vstestとNUnitの間にアダプターを書くことも考えました。
Dan Csharpster 2015年

@ DanCsharpster、あなたが見たいと思うかもしれない1つのことは、ShouldThrowとShouldNotThrowをうまくサポートする流暢なアサーションです:github.com/dennisdoomen/fluentassertions/wiki#exceptions。ドキュメントには、MSTestと互換性があると書かれています(XUnitとNUnitでのみ使用しましたが)。必要なことをすべて実行できるわけではありませんが、とにかくMSTestアサーションと組み合わせることができます。
クラークアイ2015年

11

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

もちろん、メソッド例外をキャッチすることを確認すること要件である場合、それをテストします(または、少し逆にして、キャッチするはずのスローされないことをテストします)。

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

簡単に言うと、コードをしなければならないかに焦点を当て、それをテストします。


10
-1例外がスローされないようにする必要があるポジティブな機能について考えることができます。1つは、例外を処理することを目的とするメソッドで、例外をさらにスローせずに、それらをログに記録してアクションを実行します。あなたは良い一般的なポイントを作ります-しかしそれからそれが常に真実であるかのように絶対的に話します。
ロブレビン

3
@RobLevine:私はあなたの例を理解しており、そのような場合にテストを作成することを認識しています。しかし、お気づきのように、私のポイントは確かに、より一般的な方法についてでした。いわば、コードが実行するはずのことをテストするのではなく、コードが実行しないことをテストするのです。私は自分の投稿を少し言い換えたので、私の主張はより明確になり、私が考えていたものに近づきました。また、あなたの投票を再考する機会を与えてくれます。ご説明いただきありがとうございます。返信が遅れて申し訳ありません。
km

4
反対票が削除されました-次回の反対票で私はそれほど幸せになりません!
ロブレバイン2012

4
私たちのプロジェクトにはhtmlvalidatorクラスがあり、htmlが有効でない場合は例外をスローします。たとえば、ユーザーが(コンソールを使用して)リッチコンボでJavaScriptを入力した場合です。したがって、私の場合のコードでは、例外をスローしないようにコードを実行し(ホワイトリストアプローチ)、それをテストする必要があります。
マチェーテ2014年

1
この答えに同意しません。特定のシナリオで何かがないことをテストすることは、有効なテストになる可能性があります。
bytedev 2017

7

このヘルパークラスは、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);
        }
    }
}

@Remco Beurskens-NoExceptionThrown <T>の最後に一般的なcatch {}を追加すると、他のエラーが抑制されますが、これはメソッドの意図した結果ではありません。これは、すべての例外を抑制するための汎用的な方法ではありません。既知のタイプの例外がスローされた場合にのみ失敗することを目的としています。
JJS

1
これは現在非常に古いものですが、拡張メソッドのフックとして使用できるAssertシングルトンプロパティアクセサーがThatあります。Assert.That.DoesNotThrow()よりも持っている方が、よりきれいで、より発見しやすいかもしれませんAssertEx.DoesNotThrow()。これは単なる意見です。
リチャードハウアー

3

私は見たいです Assert.Whatever一貫性を保つために、各テストの最後にです... 1つがなければ、そこにあるはずがないことを本当に確信できますか?

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

私はそのコードを誤ってそこに入れていないことを知っているので、これが意図したとおりであったことをすばやく確認するのに十分な自信を持っているはずです。

    [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

    }

それは同じではありません。コードがスローされた場合、アサーションはヒットせず、テストの実行は失敗します。条件をアサートすることにより、テストフレームワークにフックしたいとします。
DVS

1

友人のティムがExpectedExceptionについて教えてくれました。私はこのb / cが本当に好きです。それはより簡潔で、コードが少なく、例外をテストしていることを非常に明確に示しています。

[TestMethod()]
[ExpectedException(typeof(System.Exception))]
public void DivideTest()
{
    int numerator = 4;
    int denominator = 0;
    int actual = numerator / denominator;
}

詳細については、ExpectedException属性の使用法を参照してください


1
OPは例外なしを求めています。
ダニエルA.ホワイト

この答えをここに残しておきます。例外をテストする方法をグーグルで検索しているときにこの質問を見つけました。この回答はここにある必要があると思います。OPは7年前に彼らの質問に答えました。私が思う他の答えへのリンクでさえも役に立ちます。
ジェス

グッドオレティム。🤔
ラフィン
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.