Unit test exception messages with xUnit
Asked Answered
O

8

82

I'm currently converting my MsTest unit tests to xUnit. With xUnit, is there a way to test exception messages? Is it correct to test exception messages as opposed just the exception type?

Orfield answered 21/3, 2011 at 10:50 Comment(0)
R
146

I think it is correct to test for both Exception type and message. And both are easy in xUnit:

var exception = Assert.Throws<AuthenticationException>(() => DoSomething());
Assert.Equal(message, exception.Message);
Rorrys answered 18/5, 2011 at 10:11 Comment(3)
@CsabaToth No you need Assert.ThrowsAsync<> to do thisBellboy
I'm sure I'm missing the obvious, but what is the message argument in the first line for?Bigamy
@MarkEmbling thanks for pointing that out -- it was probably a typo. I updated the answer.Rorrys
F
10

Better to use the Record.Exception method as it matches the AAA pattern:

[Fact]
public void Divide_TwoNumbers_ExpectException()
{
    var sut = new Calculator();
    var exception = Record.Exception(() => sut.Divide(10, 0));
    Assert.IsType(typeof(DivideByZeroException), exception);
}

Hope this helps ...

Forebode answered 29/11, 2016 at 23:42 Comment(1)
xUnit2007: Do not use typeof(System.DivideByZeroException) expression to check the type. Instead you can use: Assert.IsType<DivideByZeroException>(exception)Arv
S
2

Something like this:

var ex = Record.Exception(() => DoSomeThing());
Assert.IsType(typeof(ArgumentNullException), ex);
Assert.Contains("Your exception message", ex.Message);
Slipstream answered 25/8, 2017 at 23:47 Comment(0)
S
1

BTW, Resharper prefers not to use typeof and suggests Assert.IsType instead, e.g.

var ex = Record.Exception(() => new FooController(null, null));
Assert.IsType<ArgumentNullException>(ex);
Sprawl answered 25/1, 2018 at 17:36 Comment(0)
S
0

An exception is no different than any other expected result of your test. It is natural to test that the message is the correct one as two different messages can come in the same exception type. However - I personally don't think of it as mandatory, at least not in all exceptions.

In our project each application exception also has a 'Message' object attached to it, so we verify the MessageId only, we don't verify that the message arguments are correct or the message's text. E.g if the message text is "Wrong parameter <{0}> was provided", we don't check that the argument that was passed to format {0} is as expected - this is not the intent. The message has a unique id - so we verify that the MessageID on the exception is 'WRONG_PARAMETER_PROVIDED'.

Schaffel answered 21/3, 2011 at 10:57 Comment(0)
O
0

xUnit uses Assert.Throws to test for exception types. You could catch the exception and Assert against the message if you needed. I think in general you want to test that the expected exception is thrown, and the exact message is really not necessary.

Assert.Throws<ArgumentNullException>()

The exception might be if you have a custom exception you are unit testing and you want to make sure the message generated is what you expect. Or if there are two ways that the same exception type can be thrown but with different messages, then asserting against the message would be valuable

Ostrogoth answered 21/3, 2011 at 10:59 Comment(1)
Throws() returns Exception -- no need to catch it.Rorrys
B
0

In the light of async stuff, new version would be

var ex = await Record.ExceptionAsync(() => myMethod(myParams));
Assert.IsType<SomeException>(ex);
Assert.Equal("My text of the error.", ex.Message);
Boyle answered 20/5, 2020 at 7:36 Comment(0)
R
0

Better to use the Record.Exception method:

[Fact]
public void Update_Record_ExpectException()
{
    var sut = new RecordData();
    var exception = Record.Exception(() => sut.Update(10));
    Assert.IsType(typeof(ArgumentNullException), exception);
}

Hope this helps ...

Research answered 12/6 at 12:30 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.