2011/06/15

Extending MbUnit With Custom Expected Exception Attributes

MbUnit provides several ways to deal with expected exceptions in the user code under test. The most popular one is certainly to decorate the test method with an [ExpectedException] attribute:
[Test, ExpectedException(typeof(ArgumentOutOfRangeException))]
public void Constructs_Foo_with_negative_value_should_throw_exception()
{
new Foo(-123);
}
Conveniently, you can use some built-in attributes to save a few more keystrokes:
[Test, ExpectedArgumentOutOfRangeException]
public void Constructs_Foo_with_negative_value_should_throw_exception()
{
new Foo(-123);
}
Those shortcut attributes are very useful. They significantly improve the readability of the tests by removing two pairs of noisy nested parenthesis.

But what if you want to define your own shortcut attribute for a custom exception of yours? Imagine for example that you use a fancy SpaceTimeBrokenException all over your code. Let's define a custom shortcut expected exception attribute for it. That's very easy with Gallio's extensibility model: you just need to derive from ExceptedExceptionAttribute like this:
using Gallio.Framework.Pattern;
using MbUnit.Framework;

[AttributeUsage(PatternAttributeTargets.Test, AllowMultiple = false, Inherited = true)]
public class ExpectedSpaceTimeBrokenExceptionAttribute : ExpectedExceptionAttribute
{
public ExpectedSpaceTimeBrokenExceptionAttribute()
: base(typeof(SpaceTimeBrokenException))
{
}

public ExpectedSpaceTimeBrokenExceptionAttribute(string message)
: base(typeof(SpaceTimeBrokenException), message)
{
}
}
That's all! Now just put that new class in a namespace accessible from your test project and enjoy it...
[Test, ExpectedSpaceTimeBrokenException]
public void Run_TimeMachine_with_negative_power_should_collapse_the_entire_universe()
{
var timeMachine = new TimeMachine();
timeMachine.Run(-1E10);
}

2 comments:

Anonymous said...

How to add a custom exception for a test ?

Yann Trevin said...

@Anonymous. Custom exceptions are created by deriving from System.Exception (more details here)