How to Use Assert to Verify That an Exception Has Been Thrown

How do I use Assert to verify that an exception has been thrown with MSTest?

For "Visual Studio Team Test" it appears you apply the ExpectedException attribute to the test's method.

Sample from the documentation here: A Unit Testing Walkthrough with Visual Studio Team Test

[TestMethod]
[ExpectedException(typeof(ArgumentException),
"A userId of null was inappropriately allowed.")]
public void NullUserIdInConstructor()
{
LogonInfo logonInfo = new LogonInfo(null, "P@ss0word");
}

How do you assert that a certain exception is thrown in JUnit tests?

It depends on the JUnit version and what assert libraries you use.

  • For JUnit5 and 4.13 see answer
  • If you use AssertJ or google-truth, see answer

The original answer for JUnit <= 4.12 was:

    @Test(expected = IndexOutOfBoundsException.class)
public void testIndexOutOfBoundsException() {

ArrayList emptyList = new ArrayList();
Object o = emptyList.get(0);

}

Though answer has more options for JUnit <= 4.12.

Reference:

  • JUnit Test-FAQ

Best way to test exceptions with Assert to ensure they will be thrown

I have a couple of different patterns that I use. I use the ExpectedException attribute most of the time when an exception is expected. This suffices for most cases, however, there are some cases when this is not sufficient. The exception may not be catchable - since it's thrown by a method that is invoked by reflection - or perhaps I just want to check that other conditions hold, say a transaction is rolled back or some value has still been set. In these cases I wrap it in a try/catch block that expects the exact exception, does an Assert.Fail if the code succeeds and also catches generic exceptions to make sure that a different exception is not thrown.

First case:

[TestMethod]
[ExpectedException(typeof(ArgumentNullException))]
public void MethodTest()
{
var obj = new ClassRequiringNonNullParameter( null );
}

Second case:

[TestMethod]
public void MethodTest()
{
try
{
var obj = new ClassRequiringNonNullParameter( null );
Assert.Fail("An exception should have been thrown");
}
catch (ArgumentNullException ae)
{
Assert.AreEqual( "Parameter cannot be null or empty.", ae.Message );
}
catch (Exception e)
{
Assert.Fail(
string.Format( "Unexpected exception of type {0} caught: {1}",
e.GetType(), e.Message )
);
}
}

How do I use Assert.Throws to assert the type of the exception?

Assert.Throws returns the exception that's thrown which lets you assert on the exception.

var ex = Assert.Throws<Exception>(() => user.MakeUserActive());
Assert.That(ex.Message, Is.EqualTo("Actual exception message"));

So if no exception is thrown, or an exception of the wrong type is thrown, the first Assert.Throws assertion will fail. However if an exception of the correct type is thrown then you can now assert on the actual exception that you've saved in the variable.

By using this pattern you can assert on other things than the exception message, e.g. in the case of ArgumentException and derivatives, you can assert that the parameter name is correct:

var ex = Assert.Throws<ArgumentNullException>(() => foo.Bar(null));
Assert.That(ex.ParamName, Is.EqualTo("bar"));

You can also use the fluent API for doing these asserts:

Assert.That(() => foo.Bar(null), 
Throws.Exception
.TypeOf<ArgumentNullException>()
.With.Property("ParamName")
.EqualTo("bar"));

or alternatively

Assert.That(
Assert.Throws<ArgumentNullException>(() =>
foo.Bar(null)
.ParamName,
Is.EqualTo("bar"));

A little tip when asserting on exception messages is to decorate the test method with the SetCultureAttribute to make sure that the thrown message is using the expected culture. This comes into play if you store your exception messages as resources to allow for localization.

How can a unit test confirm an exception has been thrown

It depends on what unit test framework you're using. In all cases you could do something like:

[Test]
public void MakeItGoBang()
{
Foo foo = new Foo();
try
{
foo.Bang();
Assert.Fail("Expected exception");
}
catch (BangException)
{
// Expected
}
}

In some frameworks there's an attribute you can add to the test method to express the expected exception, or there may be a method, such as:

[Test]
public void MakeItGoBang()
{
Foo foo = new Foo();
Assert.Throws<BangException>(() => foo.Bang());
}

It's nicer to limit the scope like this, as if you apply it to the whole test, the test could pass even if the wrong line threw the exception.

Assert an Exception using XUnit

The Assert.Throws expression will catch the exception and assert the type. You are however calling the method under test outside of the assert expression and thus failing the test case.

[Fact]
public void ProfileRepository_GetSettingsForUserIDWithInvalidArguments_ThrowsArgumentException()
{
//arrange
ProfileRepository profiles = new ProfileRepository();
// act & assert
Assert.Throws<ArgumentException>(() => profiles.GetSettingsForUserID(""));
}

If bent on following AAA you can extract the action into its own variable.

[Fact]
public void ProfileRepository_GetSettingsForUserIDWithInvalidArguments_ThrowsArgumentException()
{
//arrange
ProfileRepository profiles = new ProfileRepository();
//act
Action act = () => profiles.GetSettingsForUserID("");
//assert
ArgumentException exception = Assert.Throws<ArgumentException>(act);
//The thrown exception can be used for even more detailed assertions.
Assert.Equal("expected error message here", exception.Message);
}

Note how the exception can also be used for more detailed assertions

If testing asynchronously, Assert.ThrowsAsync follows similarly to the previously given example, except that the assertion should be awaited,

public async Task Some_Async_Test() {

//...

//Act
Func<Task> act = () => subject.SomeMethodAsync();

//Assert
var exception = await Assert.ThrowsAsync<InvalidOperationException>(act);

//...
}

I want to assert that an exception was thrown within a certain class

If you are using NUnit

Without using DataAnnotations

[Test]
public void Test_XXXXXXX
{
var yourClass = new YourClass();
Assert.That(()=>yourClass.Method(),
.Throws.Exception
.TypeOf<TypeOfYourException>
.With.Property("Message")
.EqualTo("the message you are expecting goes here")
);
}

Using DataAnnotations

[Test]
[ExpectedException(typeof(ExceptionType), ExpectedMessage="your message goes here!")]
public void Test_XXXXXXX
{
var yourClass = new YourClass();
// Call your method in a way that it will fail
yourClass.YourMethod();
}

JUnit 5: How to assert an exception is thrown?

You can use assertThrows(), which allows you to test multiple exceptions within the same test. With support for lambdas in Java 8, this is the canonical way to test for exceptions in JUnit.

Per the JUnit docs:

import static org.junit.jupiter.api.Assertions.assertThrows;

@Test
void exceptionTesting() {
MyException thrown = assertThrows(
MyException.class,
() -> myObject.doThing(),
"Expected doThing() to throw, but it didn't"
);

assertTrue(thrown.getMessage().contains("Stuff"));
}


Related Topics



Leave a reply



Submit