InfoQ made available this nice video recorded at QCon SF 2008, where my friend Jeff Brown talks about Gallio and MbUnit.
The mugs on the console can be bought on Gallio Store (Zazzle) ;)

ExpectedExceptionAttribute
(and similar) is sufficient:[Test]
[ExpectedArgumentNullException]
public void DoSomething_with_null_argument_should_throw_exception()
{
var foo = new Foo();
foo.DoSomething(null);
}
Foo
constructor could have thrown the same exception; and it would make your test completely irrelevant because it would pass for a wrong reason.Assert.Throws
method, which solves all those limitations. It is very easy to use, in particular with the lambda expression syntax.[Test]
public void DoSomething_with_null_argument_should_throw_exception()
{
var foo = new Foo();
Assert.Throws<ArgumentNullException>(() => foo.DoSomething(null));
}
ExpectedArgumentNullExceptionAttribute
is no longer needed. Now, you are sure that the exception was thrown when passing a null reference to the DoSomething
method, and not before, in an obscure part of the Foo
constructor.But wait! you can do even more! Unlike most of the other MbUnit assertion methods which just return void, Assert.Throws
returns the instance of the exception which was caught. With that instance, you can make some more interesting assertions:[Test]
public void DoSomething_with_null_argument_should_throw_exception()
{
var foo = new Foo();
var exception = Assert.Throws<ArgumentNullException>(() => foo.DoSomething(null));
Assert.AreEqual("Detected breach in space-time continuum.", exception.Message);
}
TargetInvocationException
instance, which makes the reason for the error a bit less discoverable:public Foo2
{
public void SetInt32(int value) { // ... }
public void SetDouble(double value) { // ... }
public void SetInt16(short value) { // ... }
}
[Test]
[Row(typeof(int), 9999, "SetInt32")]
[Row(typeof(double), 9999.9, "SetDouble")]
[Row(typeof(short), 9999, "SetInt16")]
public void Set_too_large_value_should_throw_exception<T>(T tooLargeValue, string methodName)
{
var foo2 = new Foo2();
var method = typeof(Foo2).GetMethod(methodName);
var exception = Assert.Throws<TargetInvocationException>(() => method.Invoke(foo2, new object[] { tooLargeValue }));
Assert.IsInstanceOfType<ArgumentOutOfRangeException>(exception.InnerException);
}