14

I have some cases where I don't care what exception is thrown (as long as some exception is thrown). Unfortunately,

Assert.Throws<Exception>(someDelegate); 

doesn't pass unless exactly an instance of Exception (so not an instance of a derived class) is thrown. I know I can obtain the behavior I want with

Exception exception = Record.Exception(someDelegate); Assert.NotNull(exception); 

but it doesn't read right. Am I missing something in xUnit that has the behavior I want? Here are two tests that indicate what I mean:

[Fact] public void Throws_exception_and_passes() { Exception exception = Record.Exception( () => { throw new InvalidOperationException(); } ); Assert.NotNull(exception); } [Fact] public void Throws_exception_and_fails() { Assert.Throws<Exception>( () => { throw new InvalidOperationException(); } ); } 

6 Answers 6

8

Per the documentation here:

http://xunit.codeplex.com/wikipage?title=HowToUse&referringTitle=Home

You have to specify the type of exception you want to be thrown. In general, this is good practice. You should be able to predict what scenarios a test would throw what type of exception. You should be able to design both you method and your test in a way that will allow you to predict this.

There are ways around this, like doing a try catch yourself, but you should look into changing your design a bit.

Sign up to request clarification or add additional context in comments.

2 Comments

Agree completely with the text. Just wanted to add that @Jon Hanna' answer details the now-built-in ThrowsAny which implements the OP's desired behavior
link is broken. xUnit has moved to github
5

It didn't exist at the time of this question, but now one can use Assert.ThrowsAny<Exception> to test for any exception derived from Exception (and hence any exception at all), along with variants such as Assert.ThrowsAny<ArgumentException> which would test for any exception derived from ArgumentException and so on.

1 Comment

This answers the question but the answer from poindexter is worth to take into consideration before actually writing your tests.
2

As you've identified if Assert.Throws<T> doesn't fit the bill, the only OOTB thing in xUnit you're left with is using Record.Exception.

As you've identified, the main way of doing a 'Assert throws anything` is to do

Assert.NotNull( Record.Exception( lambda )) 

Look at it - not pretty. This is likely by design; there are very few things in xUnit.net that are by accident (as opposed to carefully considered opinionated design).

Record.Exception returns a result for a reason (and if you were using F#, you'd have to |> ignore to chuck away the value). You should always be able to Assert something about the nature of the Exception that's happening so that an actual problem in your code doesn't get ignored by chance as you change your code over time, which is the reason for all this testing stuff in the first place. Perhaps that might take the form of

var exception = Record.Exception( sut.Something ); Assert.True( typeof(SomeException).IsAssignableFrom( exception ) ); 

Looking at that, it's safer that an Assert.NotNull(), but still doesn't feel right. It's time to, as discussed in GOOS, listen to your tests (and in the case of an opinionated test framework, your test framework).


The biggest problem in your question is however that in a real example from a real test, there is always a way to make your interface clearer or express your expectation in another way, so the real answer is Mu.

Comments

2

xUnit won't stand in your way if you want to do your own Custom Assertion, something like:

public static bool Throws<T>(this Action action, bool discardExceptions = false) where T : Exception { try { action.Invoke(); } catch (T) { return true; } catch (Exception) { if (discardExceptions) { return false; } throw; } return false; } 

Or:

public static bool Throws(this Action action) { try { action.Invoke(); } catch (Exception) { return true; } return false; } 

2 Comments

Note: You must make shure that xUnits internal Assert-Exceptions are not filtered out by adding an extra catch for that that rethrows the internal exception
Thanks k3b. Also, use this carefully because things will get messy if the action your'e invoking has side effects elsewhere. I don't know if xUnit uses a similar method, but I guess you could check easily enough.
1

I was just looking in the xUnit.net source and here is the culprit:

private static Exception Throws(Type exceptionType, Exception exception) { Guard.ArgumentNotNull("exceptionType", exceptionType); if (exception == null) throw new ThrowsException(exceptionType); if (!exceptionType.Equals(exception.GetType())) throw new ThrowsException(exceptionType, exception); return exception; } 

What would solve your problem is if this change were applied:

if(!exceptionType.Equals(exception.GetType())) 

to:

if(!exception.GetType().IsAssignableTo(exceptionType)) 

You could possibly offer to submit a patch?

1 Comment

As alluded to in my answer, there is no 'culprit' here. There is zero chance that this was written in this way by coincidence - the idea is that tests should be specific about what exceptions are thrown in what situations as ultimately exceptions are part of the interface. @rmx's answer addresses how one might write something that does that the OP expects and stackoverflow.com/a/32468935/11635 describes the now-built-in- ThrowsAny
0
 public static void SuppressException<TSut>(this TSut value, Action<TSut> action) where TSut : class { try { action.Invoke(value); } catch (Exception) { //do nothing } } 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.