A new version of NUnit is released and there is a new way to handle expected exceptions. Until recently NUnit did this by putting an attribute on your test method, very much how MsTest still works.
[TestMethod]
[ExpectedException(typeof(NullReferenceException))]
public void NullReferenceExceptionTestInMsTest()
{
/* Setup */
string[] names = null;
int numberOfNames = 0;
/* Test */
numberOfNames = names.Length;
}
You read by the method header that this test is throwing an exception. The test runner will catch the specified exception and try to determine if it was the expected exception thrown. The bad thing about this is that you put your assertion outside your test and that hurts readability. The NUnit team has conjured up the following solution.
[Test(Description = "Testing the new ExpectedException functionality in NUnit 2.5")]
public void NullReferenceExceptionTest()
{
/* Setup */
string[] names = null;
int numberOfNames = 0;
/* Assert */
Assert.Throws<NullReferenceException>(
/* Test */
() => numberOfNames = names.Length);
/* Assert that numberOfNames is still zero */
Assert.That(numberOfNames == 0);
}
The assert is nicely put inside the test and you can actually assert that there were now side effects from the thrown exception. This is a major improvement. What bothers me is that it looks like my first assertion comes before the test. We all know that the test has to run first, because it is an argument that has to be evaluated, but this does not really look good either.
[Test(Description = "Testing the new ExpectedException functionality in NUnit 2.5")]
public void NullReferenceExceptionTest()
{
/* Setup */
string[] names = null;
int numberOfNames = 0;
/* Test */
TestDelegate throwingCode = () => numberOfNames = names.Length;
/* Assert */
Assert.Throws<NullReferenceException>(throwingCode);
/* Assert that numberOfNames is still zero */
Assert.That(numberOfNames == 0);
}
Pretty neat, huh! Keep it up, NUnit team! You know that we all love you.

3 Comments
Mikael Lundin said
Interesting points. When there's several ways to do the same thing, I usually try to pick the one I find most readable.
Assert.That(numberOfNames == 0);
Assert.AreEquals(0, numberOfNames);
Why I prefer no. 1 in this case, is that I don't have to know what value is expected and what was the result as I do in no. 2. That was a big problem for me when I started out with unit testing, and because my code is more often read by other people than myself I would prefer the first syntax.
Then someone might argue that it does not matter, except in the error message we get back from NUnit. "Expected 2 but got 0" and after a while you find out that 0 was expected and 2 was the value we got. Then again, the message from a failed Assert.That is not very informative. So, I guess that would just come up to how you named the test itself, and make sure that the test only tests one thing which would be false in my examples above.
One could argue back and fourth, and it seems like a small issue in a world with much harder problems to solve.
Jens said
I Would disagree with the 3rd example, I prefere the second.
I don't see "Assert.Throws" as differently to the use of "Assert.IsTrue", "Assert.AreEqual" ect. as in a "What happens in here gives this result"...
Your argument would let me say that your "Assert.That" should be:
//Test
bool testResult = (numberOfNames == 0);
//Assert
Assert.IsTrue(testResult);
Thats rubish right?...
I'm guessing that since you seem to prefer the "Assert.That" syntax, you would prefer:
Assert.That(()=>numberOfNames = names.Length, Throws.Exception);
It appears they have thought of that, but I can't get it to work, personally I prefere the old syntax, if you ask me, Assert.That is less readable, after all fluent API's is only really more readable if we setup very advanced models, I don't see Unit tests as a place that will ever happen.
Jens said
Better clarify that when I say old syntax here, i refer to:
Assert.AreEquals
Assert.IsTrue
Assert.IsNotNull
ect.
I Absolutely LOVE the new Assert.Throws synax as well... :)