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");