Test exceptions junit java

Testing exceptions in JUnit

Let’s learn the steps involved in Testing exceptions using JUnit framework. In this post, we will learn how to test methods that throw exceptions in the code. Testing exceptions is common in automation testing, in unit testing or in testing negative test cases. For example, you try to open a non-existent file with the application and check if it throws or handles the exception case. (FileNotFoundException)

We use the clause @Test(expected=) to test the method. If the method throws the exception or any subclass of the specified exception class, the method would be marked as pass.

JUnit listing

package com.testingdocs.junit; /** * A sample JUnit4 Test demo to test exceptions */ /** * @author testingdocs * */ import static org.junit.Assert.*; import org.junit.Test; public class JUnit4ExceptionTest < @Test(expected=Exception.class) public void exceptionTest() throws Exception < //This test will pass as the method code throws // an exception. This is what expected by the test. throw new Exception("Sample exception"); >>

The test would be marked as pass, even if the test method throws an exception which is a subclass of the specified exception in the @Test expected clause.

Exception is the super class of FileNotFoundException. Hence, the test is marked as success.

Let’s see another example of unrelated exceptions and the method would be marked as an error by JUnit.

Читайте также:  Задать длину массива java

Sample Listing

package com.testingdocs.junit; /** * A sample JUnit4 Test demo to test exceptions */ /** * @author testingdocs * */ import static org.junit.Assert.*; import java.io.IOException; import org.junit.Test; public class JUnit4ExceptionTest < @Test(expected=IOException.class) public void exceptionTest() throws Exception < //This test will fail as the method code throws // an exception not related to the specified exception // in the @Test expected clause. throw new ArrayIndexOutOfBoundsException("File Not found exception"); >>Testing Exceptions JUnit

Exercise:

Run the below code and fill in the blank. You can neglect the package declaration.

Add JUnit4 library to the project.

package com.testingdocs.junit; /** * A sample JUnit4 Test demo to test exceptions */ /** * @author testingdocs * */ import static org.junit.Assert.*; import java.io.IOException; import org.junit.Test; public class JUnit4ExceptionTest < @Test(expected=IOException.class) public void exceptionTest() throws Exception < //This test will ____________ (fill in the blank) try < throw new IOException("File Not found exception"); >catch(IOException ioe) < >> >

Now try to run the below code and fill in the blank.

JUnit Tutorial on this website can be found at:

More information on JUnit official website:

Источник

. как в JUnit проверять ожидаемые исключения?

Иногда возникновение исключения является ожидаемым поведением системы, и в тестах нужно проверять, что оно действительно возникает.

Ниже описаны пять способов, как в тестовом фреймворке JUnit перехватить ожидаемое исключение и проверить его свойства. Первые четыре из них можно использовать в JUnit 4, а последний способ использует новые возможности JUnit 5.

В качестве примера для демонстрации возьмём тест для функции стандартной библиотеки, создающей временный файл. Будем проверять, что при попытке создания файла в несуществующей директории возникает исключение типа IOException . При этом предварительно в том же самом тесте создаётся временная директория и тут же удаляется, так что мы получаем гарантированно несуществующую директорию, в которой и пытаемся создать файл:

import org.junit.Test; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; public class MyTest  @Test public void testCreateTempFile() throws IOException  Path tmpDir = Files.createTempDirectory("tmp"); tmpDir.toFile().delete(); Path tmpFile = Files.createTempFile(tmpDir, "test", ".txt"); > >

Разумеется, в таком виде тест упадёт, а в отчёте будет написано, что возникло исключение. А нам нужно, чтобы тест в этом случае наоборот помечался как успешный. Посмотрим, как это можно исправить.

1. @Test

Самый простой способ сообщить тестовому фреймворку о том, что ожидается исключение – указать дополнительный параметр expected в аннотации @Test :

import org.junit.Test; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; public class MyTest  @Test(expected = IOException.class) public void testCreateTempFile() throws IOException  Path tmpDir = Files.createTempDirectory("tmp"); tmpDir.toFile().delete(); Path tmpFile = Files.createTempFile(tmpDir, "test", ".txt"); > >

Этот параметр должен содержать тип ожидаемого исключения. Если возникнет исключение именно такого типа – тест пройдёт успешно. Если возникнет исключение другого типа или не возникнет вовсе – тест упадёт.

  • Нельзя проверить текст сообщения или другие свойства возникшего исключения.
  • Нельзя понять, где именно возникло исключение. В рассматриваемом примере оно могло быть выброшено не тестируемой функцией, а чуть раньше, при попытке создать временную директорию. Тест даже не смог добраться до вызова тестируемой функции – но при этом в отчёте он помечается как успешно пройденный!

Вторая из упомянутых проблем настолько ужасна, что я никому никогда не рекомендую использовать этот способ.

2. try-catch

Оба недостатка можно устранить, если перехватывать исключение явно при помощи конструкции try-catch :

import org.junit.Assert; import org.junit.Test; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; public class MyTest  @Test public void testCreateTempFile() throws IOException  Path tmpDir = Files.createTempDirectory("tmp"); tmpDir.toFile().delete(); try  Path tmpFile = Files.createTempFile(tmpDir, "test", ".txt"); Assert.fail("Expected IOException"); > catch (IOException thrown)  Assert.assertNotEquals("", thrown.getMessage()); > // дальше идёт какой-то другой код // в нём тоже может появиться неожиданный IOException // если это случится -- тест упадёт > >

Если исключение возникает до блока try – тест падает, мы узнаём о том, что у него возникли проблемы.

Если тестируемая функция не выбрасывает вообще никакого исключения – мы попадаем на fail() в следующей строке, тест падает.

Если она выбрасывает исключение неподходящего типа – блок catch не ловит его, тест опять таки падает.

Успешно он завершается только тогда, когда тестируемая функция выбрасывает исключение нужного типа.

Тест стал более надёжным, он больше не пропускает баги. А в блоке catch можно проверить свойства пойманного исключения.

3. @Rule

Однако работать с конструкцией try-catch неудобно.

Чтобы избавиться от неё, можно воспользоваться правилом ExpectedException , входящим в стандартный дистрибутив JUnit 4:

import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.CoreMatchers.not; public class MyTest  @Rule public ExpectedException thrown = ExpectedException.none(); @Test public void testCreateTempFile() throws IOException  Path tmpDir = Files.createTempDirectory("tmp"); tmpDir.toFile().delete(); thrown.expect(IOException.class); thrown.expectMessage(not(equalTo(""))); Path tmpFile = Files.createTempFile(tmpDir, "test", ".txt"); thrown = ExpectedException.none(); // дальше идёт какой-то другой код // в нём тоже может появиться неожиданный IOException // если это случится -- тест упадёт > >

Теперь код имеет простую плоскую структуру, хотя общее количество строк кода, к сожалению, увеличилось.

Но главная проблема этого способа заключается в том, что проверки в таком стиле выглядят противоестественно – сначала описывается поведение, а потом вызывается функция. Конечно, это дело вкуса, но мне нравится, когда проверки располагаются после вызова тестируемой функции.

4. AssertJ / catch-throwable

Более красивый способ, использующий возможности Java 8, предлагают дополнительные библиотеки, такие как AssertJ или catch-throwable. Вот пример работы с AssertJ:

import org.junit.Test; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.catchThrowable; public class MyTest  @Test public void testCreateTempFile() throws IOException  Path tmpDir = Files.createTempDirectory("tmp"); tmpDir.toFile().delete(); Throwable thrown = catchThrowable(() ->  Files.createTempFile(tmpDir, "test", ".txt"); >); assertThat(thrown).isInstanceOf(IOException.class); assertThat(thrown.getMessage()).isNotBlank(); // дальше идёт какой-то другой код // в нём тоже может появиться неожиданный IOException // если это случится -- тест упадёт > >

Обращение к тестирумой функции оформлено в виде лямбда-выражения (анонимной функции), которое передаётся в “ловушку” для исключений catchThrowable . Она перехватывает возникающее исключение и возвращает его как результат своей работы, давая возможность сохранить его в переменную и затем проверить его свойства. При этом проверки находятся после вызова тестируемой функции, читать код легче.

А если исключение не возникнет – “ловушка” сама выбросит исключение и тест упадёт.

5. JUnit 5

Но почему нужно использовать какие-то дополнительные библиотеки, почему тестовые фреймворки сами не предоставляют удобных возможностей для работы с ожидаемыми исключениями?

Уже предоставляют. Перехват исключений в JUnit 5 выглядит очень похоже на предыдущий пример:

import org.junit.jupiter.api.Test; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertThrows; public class MyTest  @Test public void testCreateTempFile() throws IOException  Path tmpDir = Files.createTempDirectory("tmp"); tmpDir.toFile().delete(); Throwable thrown = assertThrows(IOException.class, () ->  Files.createTempFile(tmpDir, "test", ".txt"); >); assertNotNull(thrown.getMessage()); // дальше идёт какой-то другой код // в нём тоже может появиться неожиданный IOException // если это случится -- тест упадёт > >

Раньше такая возможность в JUnit отсутствовала, потому что предыдущие версии JUnit были ориентированы на более старые версии Java, где не было лямбда-выражений и написать подобный код было просто невозможно. Да, можно сделать нечто подобное с помощью анонимных классов, но это выглядит настолько ужасно, что конструкция try-catch кажется верхом изящества.

Так что если вам приходится писать тесты, в которых проверяется возникновение исключений – есть повод присмотреться к новым возможностям JUnit 5.

Алексей Баранцев

Автор: Алексей Баранцев

Если вам понравилась эта статья, вы можете поделиться ею в социальных сетях (кнопочки ниже), а потом вернуться на главную страницу блога и почитать другие мои статьи.
Ну а если вы не согласны с чем-то или хотите что-нибудь дополнить – оставьте комментарий ниже, может быть это послужит поводом для написания новой интересной статьи.

Источник

JUnit Assert Exception — JUnit 5 and JUnit 4

JUnit Assert Exception - JUnit 5 and JUnit 4

While we believe that this content benefits our community, we have not yet thoroughly reviewed it. If you have any suggestions for improvements, please let us know by clicking the “report an issue“ button at the bottom of the tutorial.

We can test expected exceptions using JUnit 5 assertThrows assertion. This JUnit assertion method returns the thrown exception, so we can use it to assert exception message too.

JUnit Assert Exception

String str = null; assertThrows(NullPointerException.class, () -> str.length()); 

JUnit 5 Assert Exception Message

Foo foo = new Foo(); Exception exception = assertThrows(Exception.class, () -> foo.foo()); assertEquals("Exception Message", exception.getMessage()); 

JUnit 4 Expected Exception

We can use JUnit 4 @Test annotation expected attribute to define the expected exception thrown by the test method.

@Test(expected = Exception.class) public void test() throws Exception

JUnit 4 Assert Exception Message

If we want to test exception message, then we will have to use ExpectedException rule. Below is a complete example showing how to test exception as well as exception message.

package com.journaldev.junit4; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; public class JUnit4TestException < @Rule public ExpectedException thrown = ExpectedException.none(); @Test public void test1() throws Exception < Foo foo = new Foo(); thrown.expect(Exception.class); thrown.expectMessage("Exception Message"); foo.foo(); >> 

That’s all for a quick roundup on testing expected exceptions in JUnit 5 and JUnit 4. You can check out more JUnit 5 examples from our GitHub Repository project.

Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases. Learn more about us

Источник

Оцените статью