«1. Введение

В этой статье мы подробно рассмотрим утверждения, доступные в JUnit.

После статей о переходе с JUnit 4 на JUnit 5 и A Guide to JUnit 5 мы подробно расскажем о различных утверждениях, доступных в JUnit 4 и JUnit 5.

Мы также расскажем о внесенных улучшениях. об утверждениях с JUnit 5.

2. Утверждения

Утверждения — это служебные методы для поддержки утверждения условий в тестах; эти методы доступны через класс Assert в JUnit 4 и Assertions в JUnit 5.

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

Давайте начнем изучать утверждения, доступные в JUnit 4.

3. Утверждения в JUnit 4

В этой версии библиотеки утверждения доступны для всех примитивных типов, объектов и массивов (либо примитивов, либо объектов). ).

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

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

Начнем с assertEquals.

3.1. assertEquals

Утверждение assertEquals проверяет, что ожидаемое и фактическое значения равны:

@Test
public void whenAssertingEquality_thenEqual() {
    String expected = "Baeldung";
    String actual = "Baeldung";

    assertEquals(expected, actual);
}

Также можно указать сообщение, которое будет отображаться, когда утверждение терпит неудачу:

assertEquals("failure - strings are not equal", expected, actual);

3.2. assertArrayEquals

Если мы хотим утверждать, что два массива равны, мы можем использовать assertArrayEquals:

@Test
public void whenAssertingArraysEquality_thenEqual() {
    char[] expected = {'J','u','n','i','t'};
    char[] actual = "Junit".toCharArray();
    
    assertArrayEquals(expected, actual);
}

Если оба массива равны нулю, утверждение будет считать их равными:

@Test
public void givenNullArrays_whenAssertingArraysEquality_thenEqual() {
    int[] expected = null;
    int[] actual = null;

    assertArrayEquals(expected, actual);
}

3.3. assertNotNull и assertNull

Когда мы хотим проверить, является ли объект нулевым, мы можем использовать утверждение assertNull:

@Test
public void whenAssertingNull_thenTrue() {
    Object car = null;
    
    assertNull("The car should be null", car);
}

Наоборот, если мы хотим утверждать, что объект не должен быть нулевым, мы можем использовать утверждение assertNotNull.

3.4. assertNotSame и assertSame

С помощью assertNotSame можно проверить, не ссылаются ли две переменные на один и тот же объект:

@Test
public void whenAssertingNotSameObject_thenDifferent() {
    Object cat = new Object();
    Object dog = new Object();

    assertNotSame(cat, dog);
}

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

3.5. assertTrue и assertFalse

В случае, если мы хотим проверить, является ли определенное условие истинным или ложным, мы можем соответственно использовать утверждение assertTrue или assertFalse:

@Test
public void whenAssertingConditions_thenVerified() {
    assertTrue("5 is greater then 4", 5 > 4);
    assertFalse("5 is not greater then 6", 5 > 6);
}

3.6. fail

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

Давайте посмотрим, как мы можем использовать его в первом сценарии:

@Test
public void whenCheckingExceptionMessage_thenEqual() {
    try {
        methodThatShouldThrowException();
        fail("Exception not thrown");
    } catch (UnsupportedOperationException e) {
        assertEquals("Operation Not Supported", e.getMessage());
    }
}

3.7. assertThat

Утверждение assertThat — единственное в JUnit 4, которое имеет обратный порядок параметров по сравнению с другими утверждениями.

В этом случае утверждение имеет необязательное сообщение об ошибке, фактическое значение и объект Matcher.

Давайте посмотрим, как мы можем использовать это утверждение, чтобы проверить, содержит ли массив определенные значения:

@Test
public void testAssertThatHasItems() {
    assertThat(
      Arrays.asList("Java", "Kotlin", "Scala"), 
      hasItems("Java", "Kotlin"));
}

Дополнительная информация о мощном использовании утверждения assertThat с объектом Matcher доступна в Testing with Hamcrest.

4. Утверждения JUnit 5

JUnit 5 сохранил многие методы утверждений JUnit 4, но добавил несколько новых, использующих преимущества поддержки Java 8.

Также в этой версии библиотеки утверждения доступны для всех примитивных типов, объектов и массивов (либо примитивов, либо объектов).

Порядок параметров утверждений изменен, параметр выходного сообщения перемещен в качестве последнего параметра. Благодаря поддержке Java 8 выходное сообщение может быть поставщиком, что позволяет проводить его ленивую оценку.

Давайте начнем обзор утверждений, доступных также в JUnit 4.

4.1. утвердить массив равных

«Утверждение assertArrayEquals проверяет равенство ожидаемого и фактического массивов:

@Test
public void whenAssertingArraysEquality_thenEqual() {
    char[] expected = { 'J', 'u', 'p', 'i', 't', 'e', 'r' };
    char[] actual = "Jupiter".toCharArray();

    assertArrayEquals(expected, actual, "Arrays should be equal");
}

Если массивы не равны, в качестве вывода будет отображаться сообщение «Массивы должны быть равны».

4.2. assertEquals

В случае, если мы хотим утверждать, что два числа с плавающей запятой равны, мы можем использовать простое утверждение assertEquals:

@Test
public void whenAssertingEquality_thenEqual() {
    float square = 2 * 2;
    float rectangle = 2 * 2;

    assertEquals(square, rectangle);
}

Однако, если мы хотим утверждать, что фактическое значение отличается на предопределенную дельту от ожидаемого значения , мы по-прежнему можем использовать assertEquals, но мы должны передать дельта-значение в качестве третьего параметра:

@Test
public void whenAssertingEqualityWithDelta_thenEqual() {
    float square = 2 * 2;
    float rectangle = 3 * 2;
    float delta = 2;

    assertEquals(square, rectangle, delta);
}

4.3. assertTrue и assertFalse

С помощью утверждения assertTrue можно проверить, что предоставленные условия верны:

@Test
public void whenAssertingConditions_thenVerified() {
    assertTrue(5 > 4, "5 is greater the 4");
    assertTrue(null == null, "null is equal to null");
}

Благодаря поддержке лямбда-выражения можно указать BooleanSupplier для утверждения вместо логического условия. .

Давайте посмотрим, как мы можем подтвердить правильность BooleanSupplier, используя утверждение assertFalse:

@Test
public void givenBooleanSupplier_whenAssertingCondition_thenVerified() {
    BooleanSupplier condition = () -> 5 > 6;

    assertFalse(condition, "5 is not greater then 6");
}

4.4. assertNull и assertNotNull

Когда мы хотим утверждать, что объект не является нулевым, мы можем использовать утверждение assertNotNull:

@Test
public void whenAssertingNotNull_thenTrue() {
    Object dog = new Object();

    assertNotNull(dog, () -> "The dog should not be null");
}

В обратном случае мы можем использовать утверждение assertNull, чтобы проверить, является ли фактический объект нулевым: ~ ~~

@Test
public void whenAssertingNull_thenTrue() {
    Object cat = null;

    assertNull(cat, () -> "The cat should be null");
}

В обоих случаях сообщение об ошибке будет получено ленивым способом, поскольку это поставщик.

4.5. assertSame и assertNotSame

Когда мы хотим утверждать, что ожидаемое и действительное относятся к одному и тому же объекту, мы должны использовать утверждение assertSame:

@Test
public void whenAssertingSameObject_thenSuccessfull() {
    String language = "Java";
    Optional<String> optional = Optional.of(language);

    assertSame(language, optional.get());
}

В противоположном случае мы можем использовать утверждение assertNotSame.

4.6. fail

Утверждение о сбое не проходит тест с предоставленным сообщением об ошибке, а также с основной причиной. Это может быть полезно, чтобы пометить тест, когда его разработка еще не завершена:

@Test
public void whenFailingATest_thenFailed() {
    // Test not completed
    fail("FAIL - test not completed");
}

4.7. assertAll

Одним из новых утверждений, представленных в JUnit 5, является assertAll.

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

Давайте определим сгруппированное утверждение:

@Test
public void givenMultipleAssertion_whenAssertingAll_thenOK() {
    assertAll(
      "heading",
      () -> assertEquals(4, 2 * 2, "4 is 2 times 2"),
      () -> assertEquals("java", "JAVA".toLowerCase()),
      () -> assertEquals(null, null, "null is equal to null")
    );
}

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

4.8. assertIterableEquals

assertIterableEquals утверждает, что ожидаемые и фактические итерируемые объекты полностью равны.

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

Учитывая это, давайте посмотрим, как мы можем утверждать, что два списка разных типов (например, LinkedList и ArrayList) равны: считаются равными.

@Test
public void givenTwoLists_whenAssertingIterables_thenEquals() {
    Iterable<String> al = new ArrayList<>(asList("Java", "Junit", "Test"));
    Iterable<String> ll = new LinkedList<>(asList("Java", "Junit", "Test"));

    assertIterableEquals(al, ll);
}

4.9. assertLinesMatch

assertLinesMatch утверждает, что ожидаемый список String соответствует фактическому списку.

Этот метод отличается от assertEquals и assertIterableEquals тем, что для каждой пары ожидаемых и фактических строк он выполняет следующий алгоритм:

Давайте посмотрим, как мы можем использовать это утверждение, чтобы утверждать, что два списка String имеют совпадающие строки: ~ ~~

  1. check if the expected line is equal to the actual one. If yes it continues with the next pair
  2. treat the expected line as a regular expression and performs a check with the String.matches() method. If yes it continues with the next pair
  3. check if the expected line is a fast-forward marker. If yes apply fast-forward and repeat the algorithm from the step 1

4.10. assertNotEquals

@Test
public void whenAssertingEqualityListOfStrings_thenEqual() {
    List<String> expected = asList("Java", "\\d+", "JUnit");
    List<String> actual = asList("Java", "11", "JUnit");

    assertLinesMatch(expected, actual);
}

В дополнение к assertEquals, утверждение assertNotEquals утверждает, что ожидаемое и фактическое значения не равны:

Если оба значения равны нулю, утверждение не выполняется.

@Test
public void whenAssertingEquality_thenNotEqual() {
    Integer value = 5; // result of an algorithm
    
    assertNotEquals(0, value, "The result cannot be 0");
}

4.11. assertThrows

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

Давайте посмотрим, как мы можем утвердить сгенерированное исключение:

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

@Test
void whenAssertingException_thenThrown() {
    Throwable exception = assertThrows(
      IllegalArgumentException.class, 
      () -> {
          throw new IllegalArgumentException("Exception message");
      }
    );
    assertEquals("Exception message", exception.getMessage());
}

4.12. assertTimeout и assertTimeoutPreemptively

В случае, если мы хотим утверждать, что выполнение предоставленного исполняемого файла заканчивается до заданного времени ожидания, мы можем использовать утверждение assertTimeout:

«

@Test
public void whenAssertingTimeout_thenNotExceeded() {
    assertTimeout(
      ofSeconds(2), 
      () -> {
        // code that requires less then 2 minutes to execute
        Thread.sleep(1000);
      }
    );
}

«Однако с утверждением assertTimeout предоставленный исполняемый файл будет выполняться в том же потоке вызывающего кода. Следовательно, выполнение поставщика не будет прервано превентивно, если тайм-аут превышен.

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

Оба утверждения могут принимать вместо исполняемого объекта ThrowingSupplier, представляющий любой общий блок кода, который возвращает объект и потенциально может генерировать Throwable.

5. Заключение

В этом руководстве мы рассмотрели все утверждения, доступные как в JUnit 4, так и в JUnit 5.

Мы кратко выделили улучшения, внесенные в JUnit 5, с введением новых утверждений и поддержкой лямбды.

Как всегда, полный исходный код этой статьи доступен на GitHub.