NUnit:Assert.Throws
如何使用Assert.Throws
断言exception的types和实际的消息措辞。
像这样的东西:
Assert.Throws<Exception>( ()=>user.MakeUserActive()).WithMessage("Actual exception message")
我正在testing的方法抛出多个相同types的消息,使用不同的消息,我需要一种方法来testing根据上下文引发正确的消息。
Assert.Throws
返回抛出的exception,让你断言exception。
var ex = Assert.Throws<Exception>(() => user.MakeUserActive()); Assert.That(ex.Message, Is.EqualTo("Actual exception message"));
所以如果没有抛出exception,或者抛出了错误types的exception,那么第一个Assert.Throws
断言将失败。 但是,如果抛出了正确types的exception,那么现在可以断言你保存在variables中的实际exception。
通过使用这种模式,除了exception消息之外,你可以断言其他事情,例如在ArgumentException
和派生的情况下,你可以断言参数名是正确的:
var ex = Assert.Throws<ArgumentNullException>(() => foo.Bar(null)); Assert.That(ex.ParamName, Is.EqualTo("bar"));
你也可以使用stream利的API来做这些断言:
Assert.That(() => foo.Bar(null), Throws.Exception .TypeOf<ArgumentNullException>() .With.Property("ParamName") .EqualTo("bar"));
断言exception消息时的一点小技巧是使用SetCultureAttribute
来修饰testing方法,以确保抛出的消息正在使用期望的文化。 如果您将exception消息作为资源存储以允许进行本地化,则这将起到作用。
您现在可以使用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."));
为了扩展持久化的答案,并提供更多的NUnit的function,你可以这样做:
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"));
这个问题提出了很长时间,我意识到,但是我最近碰到了同样的事情,并build议MSTest的这个function:
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模式的冗长性感到不安,所以我使用类似这样的方式来创build对我个人更清洁的代码:
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");