Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ignoring Exceptions in xUnit.net

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(); }
    );
}
like image 668
jason Avatar asked Dec 13 '10 17:12

jason


3 Answers

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.

like image 159
poindexter12 Avatar answered Oct 17 '22 08:10

poindexter12


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.

like image 38
Jon Hanna Avatar answered Oct 17 '22 09:10

Jon Hanna


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.

like image 2
Ruben Bartelink Avatar answered Oct 17 '22 10:10

Ruben Bartelink