Monday, November 26, 2018

Using Assert.Throws and Assert.ThrowsAsync with XUnit

I keep having to dig through my old code to find instances where I've tested particular attributes about an exception being thrown. XUnit has a couple of methods that allow you to check exceptions, but I always forget exactly how they're used. Since that's pretty much what this blog is for, here it is.

The first one (
Assert.Throws
) is pretty straightforward. It accepts a parameter of type
Func<object>
that should basically be a call to the method you want to test. Let's say you want to test a method called CheckMyName in a controller called WhoController. That might look like this:
Assert.Throws<CustomException>(() => _whoController.CheckMyName());

All that test is doing is checking that when your method is called it throws an instance of CustomException (presumably you've set up the test so that something in CheckMyName causes an exception to be thrown). You can always get access to the instance of CustomException that was thrown by using the result of Throws, which - because it is generic - will be an instance of whatever type you specified (in this case, CustomException).
var actual = Assert.Throws<CustomException>(() => _whoController.CheckMyName());

Once you have the instance of CustomException you can examine individual properties or whatever else you want to do with it.


The other method provided by XUnit is for testing asynchronous methods;
Assert.ThrowsAsync<T>
. I always get screwed up with this one because of async/await and when I should use what. Assuming my test uses async (i.e. public async Task MyTestShouldDoSomething()) where do I put the await? That's would look like this:
var actual = await Assert.ThrowsAsync<CustomException>(async () => await _whoController.CheckMyName());

It seems a little tricksy, but that's how you do it. Or, at least, that's how I do it and it works. It's possible I'm using it wrong, but I know that it definitely works so I'm fine with it.