Welcome to MSDN Blogs Sign in | Join | Help
One step past Assert.Throws<>

If you’re not using xUnit (and you should be), at least consider adopting the practices they have for dealing with exceptions in unit tests. From the very first release, they moved us from this:

[ExpectedException(typeof(InvalidOperationException))]
public void WithdrawingMoreThanBalanceThrows()
{
    Account account = new Account();
    account.Deposit(100);

    account.Widthraw(200);
}

to the far-better:

public void WithdrawingMoreThanBalanceThrows()
{
    Account account = new Account();
    account.Deposit(100);

    Assert.Throws<InvalidOperationException>(delegate
                                             {
                                                 account.Widthraw(200); 
                                             });

}

But we’re still not following the 3 As pattern. Recently (not sure exactly when) they took us one step further to this (in 3.5 syntax):

public void WithdrawingMoreThanBalanceThrows()
{
    Account account = new Account();
    account.Deposit(100);

    Exception ex = Record.Exception(() => account.Widthraw(200));

    ex.ShouldBeType<InvalidOperationException>();

}

and now we are exactly where we should be :)

(I was just told that () => is called the ‘crotch operator’ today. Can’t wait to use that in a code review.)

Posted: Tuesday, July 29, 2008 5:16 PM by casper
Filed under: ,

Comments

kfarmer said:

I prefer the first.  It captures, visually, the scope of the exceptional case.  Further, if the case is progressive -- I verify that I receive an exception and move on to other things -- then the first approach makes this clearer.

Especially if a test fails, in which case you'll enter the debugger at the failing case, rather than at the assertion for that case.  When a test fails, I want to be pointed as close as possible to the part that failed, in which case keeping all the actions ahead of all the assertions is precisely what you don't want.

Now, what the second could give you is some flexibility in being able to define assertion extensions on type: Assert.SomeTest(this Type, args), but I'd probably want, instead:

Assert.Exception(action)

.IsType<T>()

.HasMessage(Errors.FooError(args)); // important!  How do you know you got the right one, and how do you know it's been localized?

.. But I can get that with

Assert.ExpectedException(Exception, Action, Comparer<Exception>)

# July 29, 2008 12:59 PM

Stephen said:

Crotch operator... AHHHH I See it now :)

# July 29, 2008 5:31 PM
Leave a Comment

(required) 

(required) 

(optional)

(required) 

  
Enter Code Here: Required

Comment Notification

If you would like to receive an email when updates are made to this post, please register here

Subscribe to this post's comments using RSS

Page view tracker