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
проверяет, равны ли ожидаемые и фактические значения:
@Test
public void whenAssertingEquality_thenEqual() {
String expected = "ForEach";
String actual = "ForEach";
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);
}
Если оба массива равны null
, утверждение будет считать их равными:
@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
и утверждениеSame
С помощью assertNotSame
можно проверить, не ссылаются ли две переменные на один и тот же объект:
@Test
public void whenAssertingNotSameObject_thenDifferent() {
Object cat = new Object();
Object dog = new Object();
assertNotSame(cat, dog);
}
В противном случае, когда мы хотим убедиться, что две переменные ссылаются на один и тот же объект, мы можем использовать утверждение assertSame
.
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. потерпеть неудачу
Утверждение о сбое не проходит тест, вызывая
AssertionFailedError
. Его можно использовать для проверки фактического возникновения исключения или когда мы хотим, чтобы тест не прошел во время его разработки.
Давайте посмотрим, как мы можем использовать его в первом сценарии:
@Test
public void whenCheckingExceptionMessage_thenEqual() {
try {
methodThatShouldThrowException();
fail("Exception not thrown");
} catch (UnsupportedOperationException e) {
assertEquals("Operation Not Supported", e.getMessage());
}
}
3.7. утверждать, что
Утверждение 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 выходное сообщение может быть Supplier
, что позволяет проводить его ленивую оценку.
Давайте приступим к просмотру утверждений, у которых уже есть эквивалент JUnit 4.
4.1. assertArrayEquals
Утверждение 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
:
@Test
void whenAssertingEquality_thenEqual() {
float square = 2 * 2;
float rectangle = 2 * 2;
assertEquals(square, rectangle);
}
Однако, если мы хотим утверждать, что фактическое значение отличается на предопределенную дельту от ожидаемого значения, мы все еще можем использовать assertEquals
, но мы должны передать значение дельты в качестве третьего параметра:
@Test
void whenAssertingEqualityWithDelta_thenEqual() {
float square = 2 * 2;
float rectangle = 3 * 2;
float delta = 2;
assertEquals(square, rectangle, delta);
}
4.3. assertTrue
и assertFalse
С утверждением assertTrue
можно проверить, что предоставленные условия верны
:
@Test
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
void whenAssertingNotNull_thenTrue() {
Object dog = new Object();
assertNotNull(dog, () -> "The dog should not be null");
}
И наоборот, мы можем использовать утверждение assertNull
, чтобы проверить, является ли фактическое значение null
:
@Test
public void whenAssertingNull_thenTrue() {
Object cat = null;
assertNull(cat, () -> "The cat should be null");
}
В обоих случаях сообщение об ошибке будет получено ленивым способом, поскольку это Supplier
.
4.5. assertSame
и assertNotSame
Когда мы хотим утверждать, что ожидаемое и действительное относятся к одному и тому же объекту
, мы должны использовать утверждение assertSame
:
@Test
void whenAssertingSameObject_thenSuccessfull() {
String language = "Java";
Optional<String> optional = Optional.of(language);
assertSame(language, optional.get());
}
И наоборот, мы можем использовать assertNotSame
.
4.6. потерпеть неудачу
Утверждение о сбое не
проходит тест с предоставленным сообщением об ошибке, а также с основной причиной. Это может быть полезно, чтобы пометить тест, когда его разработка еще не завершена:
@Test
public void whenFailingATest_thenFailed() {
// Test not completed
fail("FAIL - test not completed");
}
4.7. утверждать все
Одним из новых утверждений, представленных в JUnit 5, является assertAll
.
Это утверждение позволяет создавать сгруппированные утверждения, в которых все утверждения выполняются, а их ошибки сообщаются вместе. В деталях это утверждение принимает заголовок, который будет включен в строку сообщения для MultipleFailureError
и поток
исполняемого файла
. ``
Давайте определим сгруппированное утверждение:
@Test
void givenMultipleAssertion_whenAssertingAll_thenOK() {
Object obj = null;
assertAll(
"heading",
() -> assertEquals(4, 2 * 2, "4 is 2 times 2"),
() -> assertEquals("java", "JAVA".toLowerCase()),
() -> assertNull(obj, "obj is null")
);
}
Выполнение сгруппированного утверждения прерывается только тогда, когда один из исполняемых файлов выдает исключение из черного списка ( например , OutOfMemoryError
).
4.8. assertIterableEquals
assertIterableEquals утверждает ,
что ожидаемые и фактические итерации полностью равны.
Чтобы быть равными, обе итерации должны возвращать одинаковые элементы в одном и том же порядке, и не требуется, чтобы две итерации были одного типа, чтобы быть равными.
С учетом этого давайте посмотрим, как мы можем утверждать, что два списка разных типов ( например, LinkedList
и ArrayList
) равны:
@Test
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);
}
Точно так же, как и в assertArrayEquals
, если обе итерации имеют значение null, они считаются равными.
4.9. ассерлайнсматч
assertLinesMatch утверждает ,
что ожидаемый список String
соответствует фактическому списку.
Этот метод отличается от assertEquals
и assertIterableEquals тем
, что для каждой пары ожидаемых и фактических строк он выполняет следующий алгоритм:
- проверьте, совпадает ли ожидаемая строка с фактической. Если да, он продолжается со следующей парой
- обрабатывает ожидаемую строку как регулярное выражение и выполняет проверку с помощью
String
. Методсовпадения() .
Если да, он продолжается со следующей парой - проверьте, является ли ожидаемая строка маркером быстрой перемотки вперед. Если да, примените ускоренную перемотку вперед и повторите алгоритм с шага 1.
Давайте посмотрим, как мы можем использовать это утверждение, чтобы утверждать, что два списка String
имеют совпадающие строки:
@Test
void whenAssertingEqualityListOfStrings_thenEqual() {
List<String> expected = asList("Java", "\\d+", "JUnit");
List<String> actual = asList("Java", "11", "JUnit");
assertLinesMatch(expected, actual);
}
4.10. assertNotEquals
В дополнение к assertEquals
утверждение assertNotEquals
утверждает, что ожидаемые и фактические значения не равны:
@Test
void whenAssertingEquality_thenNotEqual() {
Integer value = 5; // result of an algorithm
assertNotEquals(0, value, "The result cannot be 0");
}
Если оба равны null
, утверждение не выполняется.
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
void whenAssertingTimeout_thenNotExceeded() {
assertTimeout(
ofSeconds(2),
() -> {
// code that requires less than 2 minutes to execute
Thread.sleep(1000);
}
);
}
Однако с утверждением assertTimeout
предоставленный исполняемый файл будет выполняться в том же потоке вызывающего кода. Следовательно, выполнение поставщика не будет прервано превентивно, если тайм-аут превышен.
Если мы хотим быть уверены, что выполнение исполняемого файла будет прервано после истечения времени ожидания, мы можем использовать утверждение assertTimeoutPreemptively
.
Оба утверждения могут принимать вместо Executable
ThrowingSupplier
, представляющий любой общий блок кода, который возвращает объект и потенциально может генерировать Throwable.
5. Вывод
В этом руководстве мы рассмотрели все утверждения, доступные как в JUnit 4, так и в JUnit 5.
Мы кратко рассказали об улучшениях, внесенных в JUnit 5, с введением новых утверждений и поддержкой лямбда-выражений.
Как всегда, полный исходный код этой статьи доступен на GitHub .