Answers:
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"));
您还可以使用fluent API进行以下声明:
Assert.That(() => foo.Bar(null),
Throws.Exception
.TypeOf<ArgumentNullException>()
.With.Property("ParamName")
.EqualTo("bar"));
或者
Assert.That(
Assert.Throws<ArgumentNullException>(() =>
foo.Bar(null)
.ParamName,
Is.EqualTo("bar"));
断言异常消息时的一个小技巧是用修饰装饰测试方法,SetCultureAttribute
以确保抛出的消息使用了预期的区域性。如果您将异常消息存储为允许本地化的资源,则这会起作用。
您现在可以使用ExpectedException
属性,例如
[Test]
[ExpectedException(typeof(InvalidOperationException),
ExpectedMessage="You can't do that!"]
public void MethodA_WithNull_ThrowsInvalidOperationException()
{
MethodA(null);
}
Assert.Throw
你可以针对精确的线你感兴趣的
Assert.That(myTestDelegate, Throws.ArgumentException
.With.Property("Message").EqualTo("your argument is invalid."));
Assert.That(myTestDelegate, Throws.ArgumentException .With.Property(nameof(ArgumentException.Message)).EqualTo("your argument is invalid."));
Exception.Message
。我仍然建议至少添加此替代方法,因为它With.Property
也可以在其他对象上使用,这种情况下可以提高代码的稳定性。
这是一个古老而又相关的问题,答案已经过时,因此我要添加当前的解决方案:
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(() => user.MakeUserActive(), "Actual exception message");