I'm completely new at C# and NUnit.
In Boost.Test there is a family of BOOST_*_THROW
macros. In Python's test module there is TestCase.assertRaises
method.
As far as I understand it, in C# with NUnit (2.4.8) the only method of doing exception test is to use ExpectedExceptionAttribute
.
Why should I prefer ExpectedExceptionAttribute
over - let's say - Boost.Test's approach? What reasoning can stand behind this design decision? Why is that better in case of C# and NUnit?
Finally, if I decide to use ExpectedExceptionAttribute
, how can I do some additional tests after exception was raised and catched? Let's say that I want to test requirement saying that object has to be valid after some setter raised System.IndexOutOfRangeException
. How would you fix following code to compile and work as expected?
[Test]
public void TestSetterException()
{
Sth.SomeClass obj = new SomeClass();
// Following statement won't compile.
Assert.Raises( "System.IndexOutOfRangeException",
obj.SetValueAt( -1, "foo" ) );
Assert.IsTrue( obj.IsValid() );
}
Edit: Thanks for your answers. Today, I've found an It's the Tests blog entry where all three methods described by you are mentioned (and one more minor variation). It's shame that I couldn't find it before :-(.
I'm surprised I haven't seen this pattern mentioned yet. David Arno's is very similar, but I prefer the simplicity of this:
try
{
obj.SetValueAt(-1, "foo");
Assert.Fail("Expected exception");
}
catch (IndexOutOfRangeException)
{
// Expected
}
Assert.IsTrue(obj.IsValid());
If you can use NUnit 2.5 there's some nice helpers there.
Assert.That( delegate { ... }, Throws.Exception<ArgumentException>())
The MbUnit syntax is
Assert.Throws<IndexOutOfRangeException>(delegate {
int[] nums = new int[] { 0, 1, 2 };
nums[3] = 3;
});
Your preferred syntax:
Assert.Raises( "System.IndexOutOfRangeException",
obj.SetValueAt( -1, "foo" ) );
woiuldn't work with C# anyway - the obj.SetValueAt would be evaluated and the result passed to Assert.Raises. If SetValue throws an exception, then you'd never get into Assert.Raises.
You could write a helper method to do it:
void Raises<T>(Action action) where T:Exception {
try {
action();
throw new ExpectedException(typeof(T));
catch (Exception ex) {
if (ex.GetType() != typeof(T)) {
throw;
}
}
}
Which allows the similar syntax of:
Assert.Raises<System.IndexOutOfRangeException>(() =>
obj.SetValueAt(-1, "foo")
;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With