「void」を返すこの1つのメソッドの単体テストを書いています。例外が発生しない場合にテストに合格するケースを1つ挙げたいと思います。C#でそれを書くにはどうすればよいですか?
Assert.IsTrue(????)
(私の推測では、これは私がチェックする方法ですが、「???」には何が入りますか)
私の質問が十分に明確であることを願っています。
「void」を返すこの1つのメソッドの単体テストを書いています。例外が発生しない場合にテストに合格するケースを1つ挙げたいと思います。C#でそれを書くにはどうすればよいですか?
Assert.IsTrue(????)
(私の推測では、これは私がチェックする方法ですが、「???」には何が入りますか)
私の質問が十分に明確であることを願っています。
回答:
例外がスローされた場合、ユニットテストはとにかく失敗します-特別なアサートを入れる必要はありません。
これは、アサーションがまったくない単体テストが表示される数少ないシナリオの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についても同じことが言えます)
NUnitでは、次を使用できます。
Assert.DoesNotThrow(<expression>);
コードが例外をスローしないことを表明します。周りにアサートがなくても例外がスローされるとテストは失敗しますが、このアプローチの価値は、テストで満たされていない期待とバグを区別できることです。また、カスタムメッセージを追加するオプションがあります。テスト出力に表示されます。わかりやすいテスト出力は、テストの失敗の原因となったコード内のエラーを見つけるのに役立ちます。
コードが例外をスローしないことを確認するためのテストを追加することは有効だと思います。たとえば、入力を検証していて、着信文字列をlongに変換する必要があるとします。文字列がnullの場合がありますが、これは許容できるため、文字列変換で例外がスローされないようにする必要があります。したがって、この機会を処理するためのコードがあり、そのテストを作成していない場合は、重要なロジックの周辺をカバーできなくなります。
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); } } }
何かが起こらないことをテストしないでください。これは、コードが壊れないことを保証するようなものです。それは一種の暗示であり、私たちは皆、壊れない、バグのないコードを目指しています。そのためのテストを書きたいですか?なぜ1つの方法だけですか?すべてのメソッドをテストして、例外をスローしないようにしませんか?その道をたどると、1つの余分なダミーのアサートレステストが終了します、コードベース内のすべてのメソッドに対してが1つ作成されます。それは価値をもたらさない。
もちろん、メソッドが例外をキャッチすることを確認することが要件である場合、それをテストします(または、少し逆にして、キャッチするはずのスローされないことをテストします)。
ただし、一般的なアプローチ/プラクティスはそのままです。テストされたコードの範囲外の人工的/あいまいな要件のテストは作成しません(通常、「機能する」または「スローしない」というテストは、次の例です。そのような-特にメソッドの責任がよく知られているシナリオでは)。
簡単に言うと、コードが何をしなければならないかに焦点を当て、それをテストします。
このヘルパークラスは、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);
}
}
}
Assert
シングルトンプロパティアクセサーがThat
あります。Assert.That.DoesNotThrow()
よりも持っている方が、よりきれいで、より発見しやすいかもしれませんAssertEx.DoesNotThrow()
。これは単なる意見です。
私は見たいです 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
}
友人のティムがExpectedExceptionについて教えてくれました。私はこのb / cが本当に好きです。それはより簡潔で、コードが少なく、例外をテストしていることを非常に明確に示しています。
[TestMethod()]
[ExpectedException(typeof(System.Exception))]
public void DivideTest()
{
int numerator = 4;
int denominator = 0;
int actual = numerator / denominator;
}
詳細については、ExpectedException属性の使用法を参照してください。