C# 如何使用 Assert.Throws 来断言异常的类型?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1609536/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How do I use Assert.Throws to assert the type of the exception?
提问by epitka
How do I use Assert.Throws
to assert the type of the exception and the actual message wording.
我如何使用Assert.Throws
来断言异常的类型和实际的消息措辞。
Something like this:
像这样的东西:
Assert.Throws<Exception>(
()=>user.MakeUserActive()).WithMessage("Actual exception message")
The method I am testing throws multiple messages of the same type, with different messages, and I need a way to test that the correct message is thrown depending on the context.
我正在测试的方法抛出多个相同类型的消息,具有不同的消息,我需要一种方法来测试根据上下文抛出正确的消息。
采纳答案by Patrik H?gne
Assert.Throws
returns the exception that's thrown which lets you assert on the exception.
Assert.Throws
返回抛出的异常,让您对异常进行断言。
var ex = Assert.Throws<Exception>(() => user.MakeUserActive());
Assert.That(ex.Message, Is.EqualTo("Actual exception message"));
So if no exception is thrown, or an exception of the wrong type is thrown, the first Assert.Throws
assertion will fail. However if an exception of the correct type is thrown then you can now assert on the actual exception that you've saved in the variable.
所以如果没有抛出异常,或者抛出了错误类型的异常,第一个Assert.Throws
断言就会失败。但是,如果抛出正确类型的异常,那么您现在可以对保存在变量中的实际异常进行断言。
By using this pattern you can assert on other things than the exception message, e.g. in the case of ArgumentException
and derivatives, you can assert that the parameter name is correct:
通过使用此模式,您可以对异常消息以外的其他内容进行断言,例如在ArgumentException
和 派生的情况下,您可以断言参数名称是正确的:
var ex = Assert.Throws<ArgumentNullException>(() => foo.Bar(null));
Assert.That(ex.ParamName, Is.EqualTo("bar"));
You can also use the fluent API for doing these asserts:
您还可以使用 fluent API 来执行这些断言:
Assert.That(() => foo.Bar(null),
Throws.Exception
.TypeOf<ArgumentNullException>()
.With.Property("ParamName")
.EqualTo("bar"));
or alternatively
或者
Assert.That(
Assert.Throws<ArgumentNullException>(() =>
foo.Bar(null)
.ParamName,
Is.EqualTo("bar"));
A little tip when asserting on exception messages is to decorate the test method with the SetCultureAttribute
to make sure that the thrown message is using the expected culture. This comes into play if you store your exception messages as resources to allow for localization.
对异常消息进行断言时的一个小技巧是用 装饰测试方法以SetCultureAttribute
确保抛出的消息使用预期的文化。如果您将异常消息存储为资源以允许本地化,这就会发挥作用。
回答by Hymanson Pope
You can now use the ExpectedException
attributes, e.g.
您现在可以使用ExpectedException
属性,例如
[Test]
[ExpectedException(typeof(InvalidOperationException),
ExpectedMessage="You can't do that!"]
public void MethodA_WithNull_ThrowsInvalidOperationException()
{
MethodA(null);
}
回答by persistent
It's a long time since this issue was raised, I realize, but I recently ran into the same thing, and suggest this function for MSTest:
自从这个问题被提出以来已经很长时间了,我意识到,但我最近遇到了同样的事情,并为 MSTest 建议了这个功能:
public bool AssertThrows(Action action) where T : Exception
{
try {action();}
catch(Exception exception)
{
if (exception.GetType() == typeof(T)) return true;
}
return false;
}
usage:
用法:
Assert.IsTrue(AssertThrows<FormatException>(delegate{ newMyMethod(MyParameter); }));
More here: http://phejndorf.wordpress.com/2011/02/21/assert-that-a-particular-exception-has-occured/
更多信息:http: //phejndorf.wordpress.com/2011/02/21/assert-that-a-particular-exception-has-occured/
回答by fre0n
To expand on persistent's answer, and to provide more of the functionality of NUnit, you can do this:
为了扩展persistent的答案,并提供更多的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;
}
Examples:
例子:
// 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"));
回答by Jordan Morris
Assert.That(myTestDelegate, Throws.ArgumentException
.With.Property("Message").EqualTo("your argument is invalid."));
回答by Savage
Since I'm disturbed by the verbosity of some of the new NUnit patterns, I use something like this to create code that is cleaner for me personally:
由于我对一些新的 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);
}
The usage is then:
用法是:
AssertBusinessRuleException(() => user.MakeUserActive(), "Actual exception message");
回答by Tvde1
This is an old yet relevant question with outdated answers so I'm adding the current solution:
这是一个古老但相关的问题,答案已经过时,所以我添加了当前的解决方案:
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);
}
This works with using Microsoft.VisualStudio.TestTools.UnitTesting;
这适用于 using Microsoft.VisualStudio.TestTools.UnitTesting;