Assert.Throws
を使用して、例外のタイプと実際のメッセージ文言をアサートするにはどうすればよいですか。
このようなもの:
Assert.Throws<Exception>(
()=>user.MakeUserActive()).WithMessage("Actual exception message")
私がテストしているメソッドは、同じタイプの異なるメッセージを持つ複数のメッセージをスローします。コンテキストに応じて正しいメッセージがスローされることをテストする方法が必要です。
Assert.Throws
は、スローされた例外を返します。これにより、例外をアサートできます。
var ex = Assert.Throws<Exception>(() => user.MakeUserActive());
Assert.That(ex.Message, Is.EqualTo("Actual exception message"));
したがって、例外がスローされない場合、または間違ったタイプの例外がスローされる場合、最初のAssert.Throws
アサーションは失敗します。ただし、正しい型の例外がスローされた場合は、変数に保存した実際の例外をアサートできます。
このパターンを使用することにより、例外メッセージ以外のことをアサートできます。 ArgumentException
および派生物の場合、パラメーター名が正しいと断言できます。
var ex = Assert.Throws<ArgumentNullException>(() => foo.Bar(null));
Assert.That(ex.ParamName, Is.EqualTo("bar"));
これらのアサートを行うために流れるようなAPIを使用することもできます。
Assert.That(() => foo.Bar(null),
Throws.Exception
.TypeOf<ArgumentNullException>()
.With.Property("ParamName")
.EqualTo("bar"));
例外メッセージをアサートするときのちょっとしたヒントは、テストメソッドをSetCultureAttribute
で修飾して、スローされたメッセージが予想されるカルチャを使用していることを確認することです。これは、例外メッセージをローカライズ可能なリソースとして保存する場合に役立ちます。
ExpectedException
属性を使用できるようになりました。
[Test]
[ExpectedException(typeof(InvalidOperationException),
ExpectedMessage="You can't do that!"]
public void MethodA_WithNull_ThrowsInvalidOperationException()
{
MethodA(null);
}
Assert.That(myTestDelegate, Throws.ArgumentException
.With.Property("Message").EqualTo("your argument is invalid."));
これは古くて関連性のある質問であり、回答が古いため、現在のソリューションを追加しています。
public void Test() {
throw new MyCustomException("You can't do that!");
}
[TestMethod]
public void ThisWillPassIfExceptionThrown()
{
var exception = Assert.ThrowsException<MyCustomException>(
() => Test(),
"This should have thrown!");
Assert.AreEqual("You can't do that!", exception.Message);
}
これはusing Microsoft.VisualStudio.TestTools.UnitTesting;
で動作します
永続的な答えを拡張し、NUnitの機能をさらに提供するには、次のようにします。
public bool AssertThrows<TException>(
Action action,
Func<TException, bool> exceptionCondition = null)
where TException : Exception
{
try
{
action();
}
catch (TException ex)
{
if (exceptionCondition != null)
{
return exceptionCondition(ex);
}
return true;
}
catch
{
return false;
}
return false;
}
例:
// No exception thrown - test fails.
Assert.IsTrue(
AssertThrows<InvalidOperationException>(
() => {}));
// Wrong exception thrown - test fails.
Assert.IsTrue(
AssertThrows<InvalidOperationException>(
() => { throw new ApplicationException(); }));
// Correct exception thrown - test passes.
Assert.IsTrue(
AssertThrows<InvalidOperationException>(
() => { throw new InvalidOperationException(); }));
// Correct exception thrown, but wrong message - test fails.
Assert.IsTrue(
AssertThrows<InvalidOperationException>(
() => { throw new InvalidOperationException("ABCD"); },
ex => ex.Message == "1234"));
// Correct exception thrown, with correct message - test passes.
Assert.IsTrue(
AssertThrows<InvalidOperationException>(
() => { throw new InvalidOperationException("1234"); },
ex => ex.Message == "1234"));
この問題が提起されてからかなりの時間が経ちましたが、私は最近同じ問題にぶつかり、MSTestにこの機能を提案しました。
public bool AssertThrows(Action action) where T : Exception
{
try {action();}
catch(Exception exception)
{
if (exception.GetType() == typeof(T)) return true;
}
return false;
}
使用法:
Assert.IsTrue(AssertThrows<FormatException>(delegate{ newMyMethod(MyParameter); }));
詳細: http://phejndorf.wordpress.com/2011/02/21/assert-that-a-particular-exception-has-occured/
私はいくつかの新しいNUnitパターンの冗長性に悩まされているので、私はこのようなものを使って個人的にきれいなコードを作成します。
public void AssertBusinessRuleException(TestDelegate code, string expectedMessage)
{
var ex = Assert.Throws<BusinessRuleException>(code);
Assert.AreEqual(ex.Message, expectedMessage);
}
public void AssertException<T>(TestDelegate code, string expectedMessage) where T:Exception
{
var ex = Assert.Throws<T>(code);
Assert.AreEqual(ex.Message, expectedMessage);
}
使用法は次のとおりです。
AssertBusinessRuleException(() => service.Create(content), "Name already exists");