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(); }
);
}
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.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With