1. That the expected exception was thrown (test in the catch block), and
2. That an exception was thrown at all (test in the finally block)
That's an awful lot of extra code to write. Tests are meant to be small. Fortunately we have a way round this - we just add the attribute [ExpectedException()].
A perfect example would be checking that calling the divide method of our calculator with a zero argument throws a DivideByZeroException. As with our earlier tests, this is really easy:
using System;
using NUnit.Framework;
namespace WindowsGame1
{
[TestFixture]
public class Calculator_Tests
{
// Omitted earlier code...
[Test]
[ExpectedException(typeof(DivideByZeroException))]
public void Divide_By_Zero_Should_Throw_Exception()
{
Calculator.DivideBy( 0 );
}
}
}
No assertions. No try-catch-finally blocks. Just one line of code (well, two if you count the attribute). Note we added the System namespace to our test class, to simplify the use of exceptions. As long as the expected exception is thrown, the test will pass. If a different one is thrown, it will fail. Likewise, if no exception is thrown it will fail.
We now have the basics in place to test boundary conditions as well. But our tests are still very basic. In order to really get to grips with testing, we would like to examine what a method is actually doing internally (both to its arguments and its own state objects). We solve this with stubs, fakes and mocks. But before we can get to that, we'll need to introduce two important coding practices:
1. Design to an interface.
2. Dependency Injection
Stay tuned!
No comments:
Post a Comment