Junit 5 Expected Exception using Assertions.assertThrows()

This example will show you how to work with expected exception using Junit 5 Assertions.assetThrows(). Junit 4 (at least 4.7 version) provides expected attribute with @Test annotation, where you can mention what exception you are expecting from your test method but Junit 5 does not provide such thing. Junit 5 provides assertThrows() that can be used to check the expected exception.

A Java unit test should verify correct exception thrown in exceptional case and no exception should be thrown in normal case. assertThrows() asserts that execution of the supplied executable throws an exception of the expectedType and returns the exception.

One of the many situations where you need to test exception thrown by a Java method is testing an API method that should throw IllegalArgumentException if arguments passed to the method are not matching to pre-conditions.

In order to test any Java method for throwing exception, you need to ensure that arguments provided to the method, from the test must result in expected Exception, otherwise JUnit test will fail.

Prerequisites

Java at least 8, Junit 5.7.0, Gradle 6.5.1 or Maven 3.6.3

Project Setup

You can create either gradle or maven based project in your favorite IDE or tool. The name of the project is java-junit-5-expected-exception.

For gradle based project you can use the following build.gradle script.

plugins {
    id 'java-library'
}

sourceCompatibility = 12
targetCompatibility = 12

repositories {
    jcenter()
}

dependencies {
    testImplementation 'org.junit.jupiter:junit-jupiter-engine:5.7.0'
	testImplementation 'org.junit.platform:junit-platform-engine:1.7.0'
}

For maven based project you can use the following pom.xml file.

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	
	<groupId>com.roytuts</groupId>
	<artifactId>java-junit-5-expected-exception</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>jar</packaging>
	
	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<java.version>at least 1.8</java.version>
	</properties>
	
	<dependencies>
		<dependency>
			<groupId>org.junit.jupiter</groupId>
			<artifactId>junit-jupiter-engine</artifactId>
			<version>5.7.0</version>
		</dependency>
		<dependency>
			<groupId>org.junit.platform</groupId>
			<artifactId>junit-platform-engine</artifactId>
			<version>1.7.0</version>
		</dependency>
	</dependencies>
	
	<build>
		<plugins>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-compiler-plugin</artifactId>
				<version>3.8.1</version>
                <configuration>
					<source>${java.version}</source>
					<target>${java.version}</target>
				</configuration>
			</plugin>
		</plugins>
	</build>
</project>

Second Converter Class

Here is an example of how to test exception thrown by a method called secsToMins(), which returns minutes as seconds/60, but before calculating minutes for given seconds it checks whether minutes are positive or not, and if minutes are zero or negative it throws IllegalArgumentException.

package com.roytuts.java.junit.expected.exception;

public class SecondsToMinutesUtils {

    public int secsToMins(int seconds) {
        if (seconds <= 0) {
            throw new IllegalArgumentException("seconds (" + seconds + ") cannot be 0 or negative");
        }
        
        return seconds / 60;
    }

}

Expected Exception – assertThrows()

Below is the example for Exception testing, you can see that testSecsToMins() method uses assertThrows() to throw the IllegalArgumentException. So for int seconds = 0;, the expected exception will work fine. When you change the value of seconds to other than 0 then you will get an exception.

package com.roytuts.java.junit.expected.exception;

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

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

public class SecondsToMinutesUtilsExceptionTest {

    private SecondsToMinutesUtils secsToMins;

    @BeforeEach
    public void setUp() throws Exception {
        secsToMins = new SecondsToMinutesUtils();
    }

    @Test
    public void testSecsToMins() {
        int seconds = 0;

        assertThrows(IllegalArgumentException.class, () -> secsToMins.secsToMins(seconds));
    }

}

The expected exception gives the following success result:

junit 5 expected exception using assertThrows

If you make, for example, int seconds = 1; you will see the following exception:

org.opentest4j.AssertionFailedError: Expected java.lang.IllegalArgumentException to be thrown, but nothing was thrown.
	at org.junit.jupiter.api.AssertThrows.assertThrows(AssertThrows.java:71)
	at org.junit.jupiter.api.AssertThrows.assertThrows(AssertThrows.java:37)
	at org.junit.jupiter.api.Assertions.assertThrows(Assertions.java:3007)
	at com.roytuts.java.junit.expected.exception.SecondsToMinutesUtilsExceptionTest.testSecsToMins(SecondsToMinutesUtilsExceptionTest.java:21)
...

That’s all on how to test expected exception using assertThrows() in JUnit 5.

Source Code

Download

Leave a Reply

Your email address will not be published. Required fields are marked *