- JUnit Test Exception Examples — How to assert an exception is thrown
- 1. Test Exception in JUnit 5 — using assertThrows() method
- 2. Test Exception in JUnit 4
- 3. Test Exception in JUnit 3
- References:
- Other JUnit Tutorials:
- About the Author:
- Ожидаемое исключение JUnit 5
- 1. Assertions API assertThrows ()
- 1.1. Синтаксис
- 1.2. Вывод теста
- 2. Ожидаемое исключение генерируемое в тесте
- 3. Сгенерировано исключение другого типа, или не сгенерировано исключение
- JUnit 5 Expected Exception – assertThrows() Example
JUnit Test Exception Examples — How to assert an exception is thrown
In this JUnit tutorial, you will learn how to assert an exception is thrown by the code under test. Suppose that we want to test the exception thrown by the setName() method in the User class below:
package net.codejava; public class User < private String name; public void setName(String name) < if (name == null) < throw new IllegalArgumentException("Username cannot be blank"); >else < if (name.length() < 3) < throw new IllegalArgumentException("Username is too short"); >else if (name.length() > 30) < throw new IllegalArgumentException("Username is too long"); >> this.name = name; > >
1. Test Exception in JUnit 5 — using assertThrows() method
JUnit 5 provides the assertThrows() method that asserts a piece of code throws an exception of an expected type and returns the exception:
assertThrows(Class expectedType, Executable executable, String message)
You put the code that can throw exception in the execute() method of an Executable type — Executable is a functional interface defined by JUnit. The message is optional, to be included in the error message printed when the test fails.
For example, the following test class implements a test method that asserts IllegalArgumentException is thrown by the setName() method of the User class:
package net.codejava; import static org.junit.jupiter.api.Assertions.assertThrows; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.function.Executable; public class UserTest < @Test public void testUsernameIsNull() < assertThrows(IllegalArgumentException.class, new Executable() < @Override public void execute() throws Throwable < User user = new User(); user.setName(null); >>); > >
If the expected exception ( IllegalArgumentException in this example) is thrown, the test succeeded, otherwise it fails.
You can see the above code uses an anonymous class of type Executable . Of course you can shorter the code with Lambda syntax:
@Test public void testUsernameIsNull() < assertThrows(IllegalArgumentException.class, () ->< User user = new User(); user.setName(null); >); >
@Test public void testUsernameIsNull() < Throwable exception = assertThrows( IllegalArgumentException.class, () -> < User user = new User(); user.setName(null); >); assertEquals("Username cannot be blank", exception.getMessage()); >
Similarly, the following method tests the case username is too short:
@Test public void testUsernameTooShort() < Throwable exception = assertThrows( IllegalArgumentException.class, () -> < User user = new User(); user.setName("Jo"); >); assertEquals("Username is too short", exception.getMessage()); >
And the following method tests the case username is too long:
@Test public void testUsernameTooLong() < Throwable exception = assertThrows( IllegalArgumentException.class, () -> < User user = new User(); user.setName("Pablo Diego Jose Franciso Picasso"); >); assertEquals("Username is too long", exception.getMessage()); >
2. Test Exception in JUnit 4
In JUnit 4.7 or above, you can test exception by using the @Rule annotation with an ExpectedException class, for example:
package net.codejava; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; public class UserTest < @Rule public ExpectedException exception = ExpectedException.none(); @Test public void testUsernameTooShort() < exception.expect(IllegalArgumentException.class); exception.expectMessage("Username is too short"); User user = new User(); user.setName("Jo"); >>
The ExpectedException object is created as a rule that expects none exception is thrown so this rule doesn’t affect all existing test methods:
@Rule public ExpectedException exception = ExpectedException.none();
Then in the test method you can use its expect() and expectMessage() to assert the type of expected exception and the exception message.
In older versions of JUnit 4, you can specify the expected exception in the @Test annotation like this:
@Test(expected = IllegalArgumentException.class) public void testUsernameIsNull()
3. Test Exception in JUnit 3
In JUnit 3, or more exactly, in any versions of JUnit you can always use Java’s try-catch structure to test exception. Here’s an example:
package net.codejava; import static org.junit.Assert.assertEquals; import static org.junit.Assert.fail; import org.junit.Test; public class UserTest < @Test public void testUserNameTooShort() < try < User user = new User(); user.setName("Jo"); fail(); >catch (IllegalArgumentException ex) < assertEquals("Username is too short", ex.getMessage()); >> >
As you can see, we use the fail() statement at the end of the catch block so if the code doesn’t throw any exception, the test fails. And we catch the expected exception by the catch clause, in which we use assertEquals() methods to assert the exception message. You can use this structure to test any exceptions.
References:
Other JUnit Tutorials:
About the Author:
Nam Ha Minh is certified Java programmer (SCJP and SCWCD). He started programming with Java in the time of Java 1.4 and has been falling in love with Java since then. Make friend with him on Facebook and watch his Java videos you YouTube.
Ожидаемое исключение JUnit 5
Это продолжение туториала по JUnit 5. Введение опубликовано здесь.
В JUnit 5, чтобы написать тестовый код, который, как ожидается, вызовет исключение, мы должны использовать Assertions.assertThrows().
В данном примере ожидается, что тестовый код в комментированном блоке вызовет исключение типа ApplicationException .
Использование Assertions.assertThrows()
@Test void testExpectedException() < ApplicationException thrown = Assertions.assertThrows(ApplicationException.class, () ->< //Code under test >); Assertions.assertEquals("some message", exception.getMessage()); >
- Assertions API assertThrows ().
- Синтаксис
- Вывод теста
- Ожидаемое исключение генерируется в тесте.
- Сгенерировано исключение другого типа, или не сгенерировано исключение
1. Assertions API assertThrows ()
1.1. Синтаксис
Метод assertThrows() утверждает, что выполнение прилагаемого исполняемого блока или лямбда — выражения вызывает исключение типа expectedType . Это перегруженный метод, который принимает следующие параметры.
static T assertThrows(Class expectedType, Executable executable) static T assertThrows(Class expectedType, Executable executable, String message) static T assertThrows(Class expectedType, Executable executable, Supplier messageSupplier)
- expectedType — ожидается, что тестовый код вызовет исключение этого типа.
- message — если исполняемый код не вызывает никаких исключений, это сообщение будет напечатано вместе с результатом FAIL.
- messageSupplier — сообщение будет извлечено из него в случае неудачи теста.
1.2. Вывод теста
Если в блоке не было генерировано исключение, executable , то assertThrows() вернет FAIL .
Если выбрасывается исключение другого типа, assertThrows() будет FAIL .
Если блок кода вызывает исключение класса, который является подтипом исключения expectedType , только тогда assertThrows() вернет PASS .
Например, если мы ожидаем, IllegalArgumentException и тест выдает ошибку NumberFormatException, тогда и вывод теста будет PASS потому что NumberFormatException расширяет класс IllegalArgumentException.
Кроме того, если мы передадим Exception.class в качестве ожидаемого типа исключения, любое исключение, выброшенное из исполняемого блока, сделает результат assertion равным PASS , поскольку Exception является супертипом для всех исключений.
2. Ожидаемое исключение генерируемое в тесте
Ниже приведен очень простой тест, который ожидает, что исключение NumberFormatException будет сгенерировано при выполнении предоставленного блока кода.
@Test void testExpectedException() < NumberFormatException thrown = Assertions.assertThrows(NumberFormatException.class, () ->< Integer.parseInt("One"); >, "NumberFormatException was expected"); Assertions.assertEquals("For input string: \"One\"", thrown.getMessage()); > @Test void testExpectedExceptionWithParentType() < Assertions.assertThrows(IllegalArgumentException.class, () ->< Integer.parseInt("One"); >); >
- В тесте testExpectedException , исполняемый код Integer.parseInt(«One») генерирует исключение NumberFormatException, если аргумент метода не является допустимым текстовым представлением числа. Метод assertThrows() ожидает это исключение, так что результат теста PASS .
- В тесте testExpectedExceptionWithParentType , мы выполняем тот же код, но на этот раз мы принимаем исключение IllegalArgumentException , родительское для NumberFormatException . Этот тест тоже проходит.
3. Сгенерировано исключение другого типа, или не сгенерировано исключение
Если исполняемый код вызывает исключение любого другого типа, то результат теста будет FAIL .
И даже если исполняемый код не вызывает никаких исключений, результат теста тоже будет FAIL .
Например, в приведенном ниже примере «1» это допустимое число, поэтому исключение не возникает. Этот тест завершится ошибкой с сообщением в консоли.
@Test void testExpectedExceptionFail() < NumberFormatException thrown = Assertions .assertThrows(NumberFormatException.class, () ->< Integer.parseInt("1"); >, "NumberFormatException error was expected"); Assertions.assertEquals("Some expected message", thrown.getMessage()); >
В этом посте мы узнали, как написать тест, ожидающий возникновение исключений. Эти тесты полезны при тестировании кода, написанного в блоках catch.
JUnit 5 Expected Exception – assertThrows() Example
In JUnit 5, to write the test code that is expected to throw an exception, we should use Assertions.assertThrows(). The following test is expected to throw an exception of type ApplicationException or its subtype.
@Test void testExpectedException() < ApplicationException thrown = Assertions.assertThrows(ApplicationException.class, () ->< //Code under test >); Assertions.assertEquals("some message", thrown.getMessage()); >
Note that in JUnit 4, we needed to use @Test(expected = NullPointerException.class) syntax.
1. Assertions assertThrows() API
The assertThrows() method asserts that execution of the supplied executable block or lambda expression throws an exception of the expectedType . It is an overloaded method and takes the following parameters.
static T assertThrows(Class expectedType, Executable executable) static T assertThrows(Class expectedType, Executable executable, String message) static T assertThrows(Class expectedType, Executable executable, Supplier messageSupplier)
- expectedType – Test code is expected to throw an exception of this type.
- message – If the executable code does not throw any exception, this message will be printed along with the FAIL result.
- messageSupplier – The message will be retrieved from it in case the test fails.
1.2. Matching Exception Type
The assertThrows() will FAIL:
- Ifno exception is thrown from the executable block
- If an exception of a different type is thrown
The assertThrows() will PASS:
- If the code block throws an exception of the specified type or a subtype. For example, if we are expecting IllegalArgumentException and the test throws NumberFormatException then also the test will PASS because NumberFormatException extends IllegalArgumentException class.
Note that if we pass Exception.class as the expected exception type, any exception thrown from the executable block will make the assertion PASS since Exception is the super-type for all exceptions.
2. Demo – Expected Exception is Thrown
Given below is a very simple test that expects NumberFormatException to be thrown when the supplied code block is executed.
@Test void testExpectedException() < NumberFormatException thrown = Assertions.assertThrows(NumberFormatException.class, () ->< Integer.parseInt("One"); >, "NumberFormatException was expected"); Assertions.assertEquals("For input string: \"One\"", thrown.getMessage()); > @Test void testExpectedExceptionWithParentType() < Assertions.assertThrows(IllegalArgumentException.class, () ->< Integer.parseInt("One"); >); >
- In testExpectedException , The executable code is Integer.parseInt(«One») which throws NumberFormatException if method argument is not a valid numeric number. The assertThrows() the method expects – so this exception so the test result is PASS .
- In testExpectedExceptionWithParentType , we are executing the same code but this time we are excepting IllegalArgumentException which is the parent of NumberFormatException . This test also passes.
3. Demo – A Different Exception Type is Thrown, or No Exception
If the executable code throws any other exception type, then the test will FAIL . And even if the executable code does not throw any exception then also test will FAIL .
For example, in below example «1» is a valid number so no exception will be thrown. This test will fail with the message in the console.
@Test void testExpectedExceptionFail() < NumberFormatException thrown = Assertions .assertThrows(NumberFormatException.class, () ->< Integer.parseInt("1"); >, "NumberFormatException error was expected"); Assertions.assertEquals("Some expected message", thrown.getMessage()); >
In this post, we learned how to write a test that expects exceptions to be thrown. These tests are helpful in testing the code written in the catch blocks.