Junit assert error

A programmer-oriented testing framework for Java. Contribute to junit-team/junit4 development by creating an account on GitHub.

How do you verify that code throws exceptions as expected?
Verifying that code completes normally is important, but making sure the code behaves as expected in exceptional situations is vital too. For example:

new ArrayList<Object>().get(0);

This code should throw an IndexOutOfBoundsException. There are multiple ways in JUnit to write a test to verify this behavior.

Using assertThrows Method

The method assertThrows has been added to the Assert class in version 4.13. With this method you can assert that a given function call (specified, for instance, as a lambda expression or method reference) results in a particular type of exception being thrown. In addition it returns the exception that was thrown, so that further assertions can be made (e.g. to verify that the message and cause are correct). Furthermore, you can make assertions on the state of a domain object after the exception has been thrown:

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThrows;
import static org.junit.Assert.assertTrue;

import java.util.ArrayList;
import java.util.List;
import org.junit.Test;

@Test
public void testExceptionAndState() {
  List<Object> list = new ArrayList<>();

  IndexOutOfBoundsException thrown = assertThrows(
      IndexOutOfBoundsException.class,
      () -> list.add(1, new Object()));

  // assertions on the thrown exception
  assertEquals("Index: 1, Size: 0", thrown.getMessage());
  // assertions on the state of a domain object after the exception has been thrown
  assertTrue(list.isEmpty());
}

Try/Catch Idiom

If you project is not yet using JUnit 4.13 or your code base does not support lambdas, you can use the try/catch idiom which prevailed in JUnit 3.x:

@Test
public void testExceptionMessage() {
  List<Object> list = new ArrayList<>();
    
  try {
    list.get(0);
    fail("Expected an IndexOutOfBoundsException to be thrown");
  } catch (IndexOutOfBoundsException anIndexOutOfBoundsException) {
    assertThat(anIndexOutOfBoundsException.getMessage(), is("Index: 0, Size: 0"));
  }
}

Be aware that fail() throws an AssertionError, so you cannot use the above idiom to verify that a method call should throw an AssertionError.

Specifying the expected annotation via the @Test annotation.

The @Test annotation has an optional parameter «expected» that takes as values subclasses of Throwable. If we wanted to verify that ArrayList throws the correct exception, we could write:

@Test(expected = IndexOutOfBoundsException.class) 
public void empty() { 
  new ArrayList<Object>().get(0); 
}

The expected parameter should be used with care. The above test will pass if any code in the method throws IndexOutOfBoundsException. Using the method you also cannot test the value of the message in the exception, or the state of a domain object after the exception has been thrown.

For these reasons, the previous approaches are recommended.

ExpectedException Rule

Another way to test exceptions is the ExpectedException rule, but that approach has been deprecated in JUnit 4.13. This rule let you indicate not only what exception you are expecting, but also the exception message you are expecting:

@Rule
public ExpectedException thrown = ExpectedException.none();

@Test
public void shouldTestExceptionMessage() throws IndexOutOfBoundsException {
  List<Object> list = new ArrayList<Object>();
 
  thrown.expect(IndexOutOfBoundsException.class);
  thrown.expectMessage("Index: 0, Size: 0");
  list.get(0); // execution will never get past this line
}

The expectMessage also lets you use Matchers, which gives you a bit more flexibility in your tests. An example:

thrown.expectMessage(CoreMatchers.containsString("Size: 0"));

Moreover, you can use Matchers to inspect the Exception, useful if it has embedded state you wish to verify. For example

import static org.hamcrest.Matchers.hasProperty;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.startsWith;

import javax.ws.rs.NotFoundException;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;

import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;

public class TestExy {
  @Rule
  public ExpectedException thrown = ExpectedException.none();

  @Test
  public void shouldThrow() {
    TestThing testThing = new TestThing();
    thrown.expect(NotFoundException.class);
    thrown.expectMessage(startsWith("some Message"));
    thrown.expect(hasProperty("response", hasProperty("status", is(404))));
    testThing.chuck();
  }

  private class TestThing {
    public void chuck() {
      Response response = Response.status(Status.NOT_FOUND).entity("Resource not found").build();
      throw new NotFoundException("some Message", response);
    }
  }
}

For an expanded discussion of the ExpectedException rule, see this blog post.

Do note that when the test calls the method under test that throws the exception, no code in the test after the method will execute (because the method under test is throwing the exception). This can lead to confusion, which is one of the reasons why ExpectedException.none() is deprecated.

Время прочтения
3 мин

Просмотры 11K

Это продолжение туториала по 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());
}

Оглавление

  1. Assertions API assertThrows ().

    • Синтаксис

    • Вывод теста

  2. Ожидаемое исключение генерируется в тесте.

  3. Сгенерировано исключение другого типа, или не сгенерировано исключение

1. Assertions API assertThrows ()

1.1. Синтаксис

Метод assertThrows() утверждает, что выполнение прилагаемого исполняемого блока или лямбда — выражения вызывает исключение типа expectedType. Это перегруженный метод, который принимает следующие параметры.

static <T extends Throwable>T assertThrows(Class<T> expectedType, Executable executable)

static <T extends Throwable>T assertThrows(Class<T> expectedType, Executable executable, String message)

static <T extends Throwable>T assertThrows(Class<T> expectedType, Executable executable, Supplier<String> 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 будет сгенерировано при выполнении предоставленного блока кода.

Оба теста выдают PASS

@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.

Хорошего изучения!!!

Скачать исходный код

This post explores some techniques for asserting exceptions in Java with JUnit.

Table of contents
  • Using trycatch with fail()
  • Using @Test with expected
  • Using @Rule with ExpectedException
  • Using assertThrows from JUnit 5
  • Using AssertJ
  • Bottom line and my thoughts

Using trycatch with fail()

In this approach, the code which is excepted to throw an exception is wrapped in a trycatch block.

Then the fail() method is called immediately after the code that should throw the exception, so that if the exception is not thrown, the test fails. Then assertions can be performed on the exception that has been caught:

import org.junit.Test;

import static org.hamcrest.CoreMatchers.instanceOf;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.fail;

public class UsingTryCatchWithFail {

    private Foo foo = new Foo();

    @Test
    public void doStuff_shouldThrowException() {

        try {

            // This method is expected to throw a FooException
            foo.doStuff();
            
            // If the exception is not thrown, the test will fail
            fail("Expected exception has not been thrown");

        } catch (FooException e) {

            assertThat(e.getMessage(), is("An exception has occurred"));
            assertThat(e.getCause(), instanceOf(IllegalStateException.class));
        }
    }
}

Using @Test with expected

In this approach, the @Test annotation is used to indicate the expected exception to be thrown in the test:

import org.junit.Test;

public class UsingTestWithExpected {

    private Foo foo = new Foo();

    @Test(expected = FooException.class)
    public void doStuff_shouldThrowException() {

        foo.doStuff();
    }
}

While it’s a simple approach, it lacks the ability of asserting both the message and the cause of the exception that has been thrown. As good exception messages are valuable, assertions on messages should be taken into account.

Also, depending on how the test is written, this approach should be discouraged: As the exception expectation is placed around the whole test method, this might not actually test what is itended to be tested, leading to false positives results, as shown below:

@Test(expected = FooException.class)
public void prepareToDoStuff_shouldSucceed_doStuff_shouldThrowException() {

    // This method may throw a FooException, which may lead to a false positive result
    foo.prepareToDoStuff();

    // This is the method that is supposed to throw the actual FooException being asserted
    foo.doStuff();
}

Using @Rule with ExpectedException

This approach uses the ExpectedException rule to assert an exception and also gives the ability of making assertions on both the message and the cause of the exeption:

import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;

import static org.hamcrest.core.IsInstanceOf.instanceOf;

public class UsingRuleWithExpectedException {

    private Foo foo = new Foo();

    @Rule
    public final ExpectedException thrown = ExpectedException.none();

    @Test
    public void doStuff_shouldThrowException() {

        thrown.expect(FooException.class);
        thrown.expectMessage("An exception has occurred");
        thrown.expectCause(instanceOf(IllegalStateException.class));

        foo.doStuff();
    }
}

While this approach attempts to fix the caveats of @Test with expected to assert the exception message and cause, it also has issues when it comes to false positives:

@Test
public void prepareToDoStuff_shouldSucceed_doStuff_shouldThrowException() {

    thrown.expect(FooException.class);
    thrown.expectMessage("An exception has occurred");
    thrown.expectCause(instanceOf(IllegalStateException.class));

    // This method may throw a FooException, which may lead to a false positive result
    foo.prepareToDoStuff();

    // This is the method that is supposed to throw the actual FooException being asserted
    foo.doStuff();
}

Finally, if the test follows Behaviour-driven Development (BDD), you’ll find that ExpectedException doesn’t use such writing style.

Using assertThrows from JUnit 5

JUnit 5 aims to solve some problems of JUnit 4 and also takes advantage of Java 8 features, such as lambdas.

When it comes to exceptions, the @Test annotation no longer can be used for indicate the expected exception. As described above, this approach may lead to false positives and doesn’t allow asserting on the exception itself.

As replacement, JUnit 5 introduced the assertThrows() method: It asserts that the execution of the supplied executable throws an exception of the expected type and returns the exception instance, so assertions can be performed on it.

The test will fail if no exception is thrown, or if an exception of a different type is thrown.

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

import static org.hamcrest.CoreMatchers.instanceOf;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.jupiter.api.Assertions.assertThrows;

public class UsingAssertThrowsFromJUnit5 {

    private Foo foo = new Foo();

    @Test
    @DisplayName("doStuff method should throw exception")
    public void doStuff_shouldThrowException() {

        Throwable thrown = assertThrows(FooException.class, () -> foo.doStuff());

        assertThat(thrown.getMessage(), is("An exception has occurred"));
        assertThat(thrown.getCause(), instanceOf(IllegalStateException.class));
    }
}

Using AssertJ

AssertJ provides a rich API for fluent assertions in Java. It aims to improve the test code readability and make the maintenance of tests easier by providing strongly-typed assertions and intuitive failure messages.

If your tests use at least Java 8, then you can use AssertJ 3.x and leverage on lambdas for asserting exceptions:

import org.junit.Test;

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.assertj.core.api.Assertions.catchThrowable;

public class UsingAssertJWithJava8 {

    private Foo foo = new Foo();

    @Test
    public void doStuff_shouldThrowException_1() {

        assertThatExceptionOfType(FooException.class)
                .isThrownBy(() -> foo.doStuff())
                .withMessage("An exception has occurred")
                .withCauseExactlyInstanceOf(IllegalStateException.class);
    }

    @Test
    public void doStuff_shouldThrowException_2() {

        assertThatThrownBy(() -> foo.doStuff())
                .isInstanceOf(FooException.class)
                .hasMessage("An exception has occurred")
                .hasCauseExactlyInstanceOf(IllegalStateException.class);
    }

    @Test
    public void doStuff_shouldThrowException_3() {

        Throwable thrown = catchThrowable(() -> foo.doStuff());

        assertThat(thrown)
                .isInstanceOf(Exception.class)
                .hasMessage("An exception has occurred")
                .hasCauseExactlyInstanceOf(IllegalStateException.class);
    }

    @Test
    public void doStuff_shouldThrowException_4() {

        FooException thrown = catchThrowableOfType(() -> foo.doStuff(), FooException.class);

        assertThat(thrown)
                .hasMessage("An exception has occurred")
                .hasCauseExactlyInstanceOf(IllegalStateException.class);
    }
}

If your tests use Java 7, then you can use the trycatch with fail() approach with AssertJ 2.x and perform fluent assertions on the exception that has been thrown:

import org.junit.Test;

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.failBecauseExceptionWasNotThrown;
import static org.junit.Assert.fail;

public class UsingAssertJWithJava7 {

    private Foo foo = new Foo();

    @Test
    public void doStuff_shouldThrowException_1() {

        try {

            foo.doStuff();
            fail("Expected exception has not been thrown");

        } catch (FooException e) {

            assertThat(e)
                    .hasMessage("An exception has occurred")
                    .hasCauseExactlyInstanceOf(IllegalStateException.class);
        }
    }

    @Test
    public void doStuff_shouldThrowException_2() {

        try {

            foo.doStuff();
            failBecauseExceptionWasNotThrown(FooException.class);

        } catch (FooException e) {

            assertThat(e)
                    .hasMessage("An exception has occurred")
                    .hasCauseExactlyInstanceOf(IllegalStateException.class);
        }
    }
}

Bottom line and my thoughts

After evaluating the approaches for asserting exceptions described above, I would avoid both @Test with expected and @Rule with ExpectedException approaches, as they may lead to false positive results.

For Java 7, simply stick to the trycatch with fail() approach, even if the test look a bit clumsy.

If you are using at least Java 8 (which I really hope you are), then you can leverage the power of lambdas for assertions. And I strongly encourage you to consider using AssertJ, as it provides a fluent API and the assertions are very close to plain English, which boosts the readability of your tests.

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

Ниже описаны пять способов, как в тестовом фреймворке 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.


In this JUnit article, we will discuss how to assert the expected exceptions thrown by the method.

1. JUnit5 – assertThrows

JUnit5 Jupiter Assertions API introduces a static method assertThrows to assert the expected exceptions.

There are multiple overloaded methods of assertThrows. All of these methods are public static and return type of Throwable.

T assertThrows(Class expectedType, Executable executable) 
T assertThrows(Class expectedType, Executable executable, String message)
T assertThrows(Class expectedType, Executable executable, Supplier messageSupplier)

Two important parameters it expects are

  • Type of exception expected
  • An executable that is expected to throw an exception. Here we can pass the code under test as a lambda expression or as a method reference.

If the executable blocks throw the expected( or any of its child) exception then the test will pass else it will fail.

@Test
void assertNullPointerException() {
  var message = "test exception";
  var expectedException =
      assertThrows(
          NullPointerException.class,
          () -> {
            throw new NullPointerException(message);
          });
  assertEquals(message, expectedException.getMessage());
}

Since assertThrows returns a Throwable we can use it to verify the message or other details of a Throwable.

It is also important to note that expected exception is valid for the mentioned exception and all of its child classes as well.

Let’s implement the previous example by replacing the expected exception from NullPointerException with RuntimeException. New test is valid and will give the same result.

assertThrows(
    RuntimeException.class,
    () -> {
      throw new NullPointerException(message);
    });

Read More: assertDoesNotThrow in JUnit5


2. JUnit4

JUnit4 provides two different ways to assert the exceptions.

Let’s discuss @Test annotation and ExpectedException rule in detail.

2.1. @Test – expected

In JUnit4, @Test annotation provides the expected attribute which can simply be used to define the exception class we are excepting.

If the executable blocks throw the expected( or any of its child) exception then the test will pass else it will fail.

@Test(expected = NullPointerException.class)
void assertNullPointerException() {
  var message = "test exception"
  throw new NullPointerException(message);
}

This method of asserting an exception is good if we just want to verify be exception type. To check the assertion details let’s discuss ExpectedException Rule.

2.2. ExpectedException Rule

ExpectedException is a class in JUnit4 that can be used to verify exceptions thrown by a method as well its details like the message, cause, etc.

@Rule
public ExpectedException expectedException = ExpectedException.none();

@Test
public void throwsExcept() {
    var message = "test exception"

    expectedException.expect(NullPointerException.class);
    expectedException.expectMessage(message);

    throw new NullPointerException(message);
}

In the example above we have used ExpectedException to verify the type and message of the exception thrown by the test method.


Complete code samples are present on Github project.


An investment in knowledge always pays the best interest. I hope you like the tutorial. Do come back for more because learning paves way for a better understanding

Do not forget to share and Subscribe.

Happy coding!! 😊

Recommended —

Содержание

  1. Ожидаемое исключение JUnit 5
  2. 1. Assertions API assertThrows ()
  3. 1.1. Синтаксис
  4. 1.2. Вывод теста
  5. 2. Ожидаемое исключение генерируемое в тесте
  6. 3. Сгенерировано исключение другого типа, или не сгенерировано исключение
  7. Java junit assert exception
  8. Assert
  9. assertTrue
  10. assertTrue
  11. assertFalse
  12. assertFalse
  13. assertEquals
  14. assertEquals
  15. assertNotEquals
  16. assertNotEquals
  17. assertNotEquals
  18. assertNotEquals
  19. assertNotEquals
  20. assertNotEquals
  21. assertNotEquals
  22. assertArrayEquals
  23. assertArrayEquals
  24. assertArrayEquals
  25. assertArrayEquals
  26. assertArrayEquals
  27. assertArrayEquals
  28. assertArrayEquals
  29. assertArrayEquals
  30. assertArrayEquals
  31. assertArrayEquals
  32. assertArrayEquals
  33. assertArrayEquals
  34. assertArrayEquals
  35. assertArrayEquals
  36. assertArrayEquals
  37. assertArrayEquals
  38. assertArrayEquals
  39. assertArrayEquals
  40. assertEquals
  41. assertEquals
  42. assertNotEquals
  43. assertEquals
  44. assertEquals
  45. assertEquals
  46. assertEquals
  47. assertEquals
  48. assertEquals
  49. assertNotNull
  50. assertNotNull
  51. assertNull
  52. assertNull
  53. assertSame
  54. assertSame
  55. assertNotSame
  56. assertNotSame
  57. assertEquals
  58. assertEquals
  59. assertThat
  60. assertThat
  61. assertThrows

Ожидаемое исключение JUnit 5

Это продолжение туториала по JUnit 5. Введение опубликовано здесь.

В JUnit 5, чтобы написать тестовый код, который, как ожидается, вызовет исключение, мы должны использовать Assertions.assertThrows().

В данном примере ожидается, что тестовый код в комментированном блоке вызовет исключение типа ApplicationException .

Использование Assertions.assertThrows()

Оглавление

Assertions API assertThrows ().

Ожидаемое исключение генерируется в тесте.

Сгенерировано исключение другого типа, или не сгенерировано исключение

1. Assertions API assertThrows ()

1.1. Синтаксис

Метод assertThrows() утверждает, что выполнение прилагаемого исполняемого блока или лямбда — выражения вызывает исключение типа expectedType . Это перегруженный метод, который принимает следующие параметры.

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 будет сгенерировано при выполнении предоставленного блока кода.

Оба теста выдают PASS

В тесте testExpectedException , исполняемый код Integer.parseInt(«One») генерирует исключение NumberFormatException, если аргумент метода не является допустимым текстовым представлением числа. Метод assertThrows() ожидает это исключение, так что результат теста PASS .

В тесте testExpectedExceptionWithParentType , мы выполняем тот же код, но на этот раз мы принимаем исключение IllegalArgumentException , родительское для NumberFormatException . Этот тест тоже проходит.

3. Сгенерировано исключение другого типа, или не сгенерировано исключение

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

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

Например, в приведенном ниже примере «1» это допустимое число, поэтому исключение не возникает. Этот тест завершится ошибкой с сообщением в консоли.

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

Источник

Java junit assert exception

A set of assertion methods useful for writing tests. Only failed assertions are recorded. These methods can be used directly: Assert.assertEquals(. ) , however, they read better if they are referenced through static import:

Constructor Summary
protected Assert ()
Protect constructor since it is a static only class
Method Summary
static void assertArrayEquals (boolean[] expecteds, boolean[] actuals)
Asserts that two boolean arrays are equal.
static void assertArrayEquals (byte[] expecteds, byte[] actuals)
Asserts that two byte arrays are equal.
static void assertArrayEquals (char[] expecteds, char[] actuals)
Asserts that two char arrays are equal.
static void assertArrayEquals (double[] expecteds, double[] actuals, double delta)
Asserts that two double arrays are equal.
static void assertArrayEquals (float[] expecteds, float[] actuals, float delta)
Asserts that two float arrays are equal.
static void assertArrayEquals (int[] expecteds, int[] actuals)
Asserts that two int arrays are equal.
static void assertArrayEquals (long[] expecteds, long[] actuals)
Asserts that two long arrays are equal.
static void assertArrayEquals (Object[] expecteds, Object[] actuals)
Asserts that two object arrays are equal.
static void assertArrayEquals (short[] expecteds, short[] actuals)
Asserts that two short arrays are equal.
static void assertArrayEquals (String message, boolean[] expecteds, boolean[] actuals)
Asserts that two boolean arrays are equal.
static void assertArrayEquals (String message, byte[] expecteds, byte[] actuals)
Asserts that two byte arrays are equal.
static void assertArrayEquals (String message, char[] expecteds, char[] actuals)
Asserts that two char arrays are equal.
static void assertArrayEquals (String message, double[] expecteds, double[] actuals, double delta)
Asserts that two double arrays are equal.
static void assertArrayEquals (String message, float[] expecteds, float[] actuals, float delta)
Asserts that two float arrays are equal.
static void assertArrayEquals (String message, int[] expecteds, int[] actuals)
Asserts that two int arrays are equal.
static void assertArrayEquals (String message, long[] expecteds, long[] actuals)
Asserts that two long arrays are equal.
static void assertArrayEquals (String message, Object[] expecteds, Object[] actuals)
Asserts that two object arrays are equal.
static void assertArrayEquals (String message, short[] expecteds, short[] actuals)
Asserts that two short arrays are equal.
static void assertEquals (double expected, double actual)
Deprecated. Use assertEquals(double expected, double actual, double delta) instead
static void assertEquals (double expected, double actual, double delta)
Asserts that two doubles are equal to within a positive delta.
static void assertEquals (float expected, float actual, float delta)
Asserts that two floats are equal to within a positive delta.
static void assertEquals (long expected, long actual)
Asserts that two longs are equal.
static void assertEquals (Object[] expecteds, Object[] actuals)
Deprecated. use assertArrayEquals
static void assertEquals (Object expected, Object actual)
Asserts that two objects are equal.
static void assertEquals (String message, double expected, double actual)
Deprecated. Use assertEquals(String message, double expected, double actual, double delta) instead
static void assertEquals (String message, double expected, double actual, double delta)
Asserts that two doubles are equal to within a positive delta.
static void assertEquals (String message, float expected, float actual, float delta)
Asserts that two floats are equal to within a positive delta.
static void assertEquals (String message, long expected, long actual)
Asserts that two longs are equal.
static void assertEquals (String message, Object[] expecteds, Object[] actuals)
Deprecated. use assertArrayEquals
static void assertEquals (String message, Object expected, Object actual)
Asserts that two objects are equal.
static void assertFalse (boolean condition)
Asserts that a condition is false.
static void assertFalse (String message, boolean condition)
Asserts that a condition is false.
static void assertNotEquals (double unexpected, double actual, double delta)
Asserts that two doubles are not equal to within a positive delta.
static void assertNotEquals (float unexpected, float actual, float delta)
Asserts that two floats are not equal to within a positive delta.
static void assertNotEquals (long unexpected, long actual)
Asserts that two longs are not equals.
static void assertNotEquals (Object unexpected, Object actual)
Asserts that two objects are not equals.
static void assertNotEquals (String message, double unexpected, double actual, double delta)
Asserts that two doubles are not equal to within a positive delta.
static void assertNotEquals (String message, float unexpected, float actual, float delta)
Asserts that two floats are not equal to within a positive delta.
static void assertNotEquals (String message, long unexpected, long actual)
Asserts that two longs are not equals.
static void assertNotEquals (String message, Object unexpected, Object actual)
Asserts that two objects are not equals.
static void assertNotNull (Object object)
Asserts that an object isn’t null.
static void assertNotNull (String message, Object object)
Asserts that an object isn’t null.
static void assertNotSame (Object unexpected, Object actual)
Asserts that two objects do not refer to the same object.
static void assertNotSame (String message, Object unexpected, Object actual)
Asserts that two objects do not refer to the same object.
static void assertNull (Object object)
Asserts that an object is null.
static void assertNull (String message, Object object)
Asserts that an object is null.
static void assertSame (Object expected, Object actual)
Asserts that two objects refer to the same object.
static void assertSame (String message, Object expected, Object actual)
Asserts that two objects refer to the same object.
static

void

assertThat (String reason, T actual, Matcher matcher)
Deprecated. use org.hamcrest.MatcherAssert.assertThat()
static

void

assertThat (T actual, Matcher matcher)
Deprecated. use org.hamcrest.MatcherAssert.assertThat()
static

T

assertThrows (Class expectedThrowable, ThrowingRunnable runnable)
Asserts that runnable throws an exception of type expectedThrowable when executed.
static

T

assertThrows (String message, Class expectedThrowable, ThrowingRunnable runnable)
Asserts that runnable throws an exception of type expectedThrowable when executed.
static void assertTrue (boolean condition)
Asserts that a condition is true.
static void assertTrue (String message, boolean condition)
Asserts that a condition is true.
static void fail ()
Fails a test with no message.
static void fail (String message)
Fails a test with the given message.
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
Constructor Detail

Assert

Method Detail

assertTrue

Parameters: message — the identifying message for the AssertionError ( null okay) condition — condition to be checked

assertTrue

Parameters: condition — condition to be checked

assertFalse

Parameters: message — the identifying message for the AssertionError ( null okay) condition — condition to be checked

assertFalse

Parameters: condition — condition to be checked

Parameters: message — the identifying message for the AssertionError ( null okay) See Also: AssertionError

assertEquals

Parameters: message — the identifying message for the AssertionError ( null okay) expected — expected value actual — actual value

assertEquals

Parameters: expected — expected value actual — the value to check against expected

assertNotEquals

Parameters: message — the identifying message for the AssertionError ( null okay) unexpected — unexpected value to check actual — the value to check against unexpected

assertNotEquals

Parameters: unexpected — unexpected value to check actual — the value to check against unexpected

assertNotEquals

Parameters: message — the identifying message for the AssertionError ( null okay) unexpected — unexpected value to check actual — the value to check against unexpected

assertNotEquals

Parameters: unexpected — unexpected value to check actual — the value to check against unexpected

assertNotEquals

Parameters: message — the identifying message for the AssertionError ( null okay) unexpected — unexpected value actual — the value to check against unexpected delta — the maximum delta between unexpected and actual for which both numbers are still considered equal.

assertNotEquals

Parameters: unexpected — unexpected value actual — the value to check against unexpected delta — the maximum delta between unexpected and actual for which both numbers are still considered equal.

assertNotEquals

Parameters: unexpected — unexpected value actual — the value to check against unexpected delta — the maximum delta between unexpected and actual for which both numbers are still considered equal.

assertArrayEquals

Parameters: message — the identifying message for the AssertionError ( null okay) expecteds — Object array or array of arrays (multi-dimensional array) with expected values. actuals — Object array or array of arrays (multi-dimensional array) with actual values Throws: org.junit.internal.ArrayComparisonFailure

assertArrayEquals

Parameters: expecteds — Object array or array of arrays (multi-dimensional array) with expected values actuals — Object array or array of arrays (multi-dimensional array) with actual values

assertArrayEquals

Parameters: message — the identifying message for the AssertionError ( null okay) expecteds — boolean array with expected values. actuals — boolean array with expected values. Throws: org.junit.internal.ArrayComparisonFailure

assertArrayEquals

Parameters: expecteds — boolean array with expected values. actuals — boolean array with expected values.

assertArrayEquals

Parameters: message — the identifying message for the AssertionError ( null okay) expecteds — byte array with expected values. actuals — byte array with actual values Throws: org.junit.internal.ArrayComparisonFailure

assertArrayEquals

Parameters: expecteds — byte array with expected values. actuals — byte array with actual values

assertArrayEquals

Parameters: message — the identifying message for the AssertionError ( null okay) expecteds — char array with expected values. actuals — char array with actual values Throws: org.junit.internal.ArrayComparisonFailure

assertArrayEquals

Parameters: expecteds — char array with expected values. actuals — char array with actual values

assertArrayEquals

Parameters: message — the identifying message for the AssertionError ( null okay) expecteds — short array with expected values. actuals — short array with actual values Throws: org.junit.internal.ArrayComparisonFailure

assertArrayEquals

Parameters: expecteds — short array with expected values. actuals — short array with actual values

assertArrayEquals

Parameters: message — the identifying message for the AssertionError ( null okay) expecteds — int array with expected values. actuals — int array with actual values Throws: org.junit.internal.ArrayComparisonFailure

assertArrayEquals

Parameters: expecteds — int array with expected values. actuals — int array with actual values

assertArrayEquals

Parameters: message — the identifying message for the AssertionError ( null okay) expecteds — long array with expected values. actuals — long array with actual values Throws: org.junit.internal.ArrayComparisonFailure

assertArrayEquals

Parameters: expecteds — long array with expected values. actuals — long array with actual values

assertArrayEquals

Parameters: message — the identifying message for the AssertionError ( null okay) expecteds — double array with expected values. actuals — double array with actual values delta — the maximum delta between expecteds[i] and actuals[i] for which both numbers are still considered equal. Throws: org.junit.internal.ArrayComparisonFailure

assertArrayEquals

Parameters: expecteds — double array with expected values. actuals — double array with actual values delta — the maximum delta between expecteds[i] and actuals[i] for which both numbers are still considered equal.

assertArrayEquals

Parameters: message — the identifying message for the AssertionError ( null okay) expecteds — float array with expected values. actuals — float array with actual values delta — the maximum delta between expecteds[i] and actuals[i] for which both numbers are still considered equal. Throws: org.junit.internal.ArrayComparisonFailure

assertArrayEquals

Parameters: expecteds — float array with expected values. actuals — float array with actual values delta — the maximum delta between expecteds[i] and actuals[i] for which both numbers are still considered equal.

assertEquals

Parameters: message — the identifying message for the AssertionError ( null okay) expected — expected value actual — the value to check against expected delta — the maximum delta between expected and actual for which both numbers are still considered equal.

assertEquals

Parameters: message — the identifying message for the AssertionError ( null okay) expected — expected value actual — the value to check against expected delta — the maximum delta between expected and actual for which both numbers are still considered equal.

assertNotEquals

Parameters: message — the identifying message for the AssertionError ( null okay) unexpected — unexpected value actual — the value to check against unexpected delta — the maximum delta between unexpected and actual for which both numbers are still considered equal.

assertEquals

Parameters: expected — expected long value. actual — actual long value

assertEquals

Parameters: message — the identifying message for the AssertionError ( null okay) expected — long expected value. actual — long actual value

assertEquals

assertEquals

assertEquals

Parameters: expected — expected value actual — the value to check against expected delta — the maximum delta between expected and actual for which both numbers are still considered equal.

assertEquals

Parameters: expected — expected value actual — the value to check against expected delta — the maximum delta between expected and actual for which both numbers are still considered equal.

assertNotNull

Parameters: message — the identifying message for the AssertionError ( null okay) object — Object to check or null

assertNotNull

Parameters: object — Object to check or null

assertNull

Parameters: message — the identifying message for the AssertionError ( null okay) object — Object to check or null

assertNull

Parameters: object — Object to check or null

assertSame

Parameters: message — the identifying message for the AssertionError ( null okay) expected — the expected object actual — the object to compare to expected

assertSame

Parameters: expected — the expected object actual — the object to compare to expected

assertNotSame

Parameters: message — the identifying message for the AssertionError ( null okay) unexpected — the object you don’t expect actual — the object to compare to unexpected

assertNotSame

Parameters: unexpected — the object you don’t expect actual — the object to compare to unexpected

assertEquals

Asserts that two object arrays are equal. If they are not, an AssertionError is thrown with the given message. If expecteds and actuals are null , they are considered equal.

Parameters: message — the identifying message for the AssertionError ( null okay) expecteds — Object array or array of arrays (multi-dimensional array) with expected values. actuals — Object array or array of arrays (multi-dimensional array) with actual values

assertEquals

Asserts that two object arrays are equal. If they are not, an AssertionError is thrown. If expected and actual are null , they are considered equal.

Parameters: expecteds — Object array or array of arrays (multi-dimensional array) with expected values actuals — Object array or array of arrays (multi-dimensional array) with actual values

assertThat

Asserts that actual satisfies the condition specified by matcher . If not, an AssertionError is thrown with information about the matcher and failing value. Example: org.hamcrest.Matcher does not currently document the meaning of its type parameter T . This method assumes that a matcher typed as Matcher can be meaningfully applied only to values that could be assigned to a variable of type T .

Type Parameters: T — the static type accepted by the matcher (this can flag obvious compile-time problems such as assertThat(1, is(«a»)) Parameters: actual — the computed value being compared matcher — an expression, built of Matcher s, specifying allowed values See Also: CoreMatchers

assertThat

Asserts that actual satisfies the condition specified by matcher . If not, an AssertionError is thrown with the reason and information about the matcher and failing value. Example: org.hamcrest.Matcher does not currently document the meaning of its type parameter T . This method assumes that a matcher typed as Matcher can be meaningfully applied only to values that could be assigned to a variable of type T .

Type Parameters: T — the static type accepted by the matcher (this can flag obvious compile-time problems such as assertThat(1, is(«a»)) Parameters: reason — additional information about the error actual — the computed value being compared matcher — an expression, built of Matcher s, specifying allowed values See Also: CoreMatchers

assertThrows

Parameters: expectedThrowable — the expected type of the exception runnable — a function that is expected to throw an exception when executed Returns: the exception thrown by runnable Since: 4.13

Источник

Понравилась статья? Поделить с друзьями:
  • Jungheinrich погрузчик ошибка 1123
  • Jungheinrich ошибка pre op
  • Jungheinrich ошибка 3167
  • Jungheinrich ошибка 3164
  • Jungheinrich ошибка 1310