Assert Methods
As you may have figured out from the simple test, most of the secret of implementing JUnit unit tests, is in the use of the assert methods in the class org.junit.Assert . In this text I will take a closer look at what assert methods are available in this class.
Here is a list of the assert methods:
Throughout the rest of this text I will explain how these assert methods work, and show you examples of how to use them. The examples will test an imaginary class called MyUnit . The code for this class is not shown, but you don’t really need the code in order to understand how to test it.
assertArrayEquals()
The assertArrayEquals() method will test whether two arrays are equal to each other. In other words, if the two arrays contain the same number of elements, and if all the elements in the array are equal to each other.
To check for element equality, the elements in the array are compared using their equals() method. More specifically, the elements of each array are compared one by one using their equals() method. That means, that it is not enough that the two arrays contain the same elements. They must also be present in the same order.
import org.junit.Test; import static org.junit.Assert.*; public class MyUnitTest < @Test public void testGetTheStringArray() < MyUnit myUnit = new MyUnit(); String[] expectedArray = ; String[] resultArray = myUnit.getTheStringArray(); assertArrayEquals(expectedArray, resultArray); > >
First the expected array is created. Second the myUnit.getTheStringArray() method is called, which is the method we want to test. Third, the result of the myUnit.getTheStringArray() method call is compared to the expected array.
If the arrays are equal, the assertArrayEquals() will proceed without errors. If the arrays are not equal, an exception will be thrown, and the test aborted. Any test code after the assertArrayEquals() will not be executed.
assertEquals()
The assertEquals() method compares two objects for equality, using their equals() method.
import org.junit.Test; import static org.junit.Assert.*; public class MyUnitTest < @Test public void testConcatenate() < MyUnit myUnit = new MyUnit(); String result = myUnit.concatenate("one", "two"); assertEquals("onetwo", result); >>
First the myUnit.concatenate() method is called, and the result is stored in the variable result .
Second, the result value is compared to the expected value «onetwo» , using the assertEquals() method.
If the two objects are equal according to their implementation of their equals() method, the assertEquals() method will return normally. Otherwise the assertEquals() method will throw an exception, and the test will stop there.
This example compared to String objects, but the assertEquals() method can compare any two objects to each other. The assertEquals() method also come in versions which compare primitive types like int and float to each other.
assertTrue() + assertFalse()
The assertTrue() and assertFalse() methods tests a single variable to see if its value is either true , or false . Here is a simple example:
import org.junit.Test; import static org.junit.Assert.*; public class MyUnitTest < @Test public void testGetTheBoolean() < MyUnit myUnit = new MyUnit(); assertTrue (myUnit.getTheBoolean()); assertFalse(myUnit.getTheBoolean()); >>
As you can see, the method call to myUnit.getTheBollean() is inlined inside the assertTrue() assertFalse() calls.
If the getTheBoolean() method returns true , the assertTrue() method will return normally. Otherwise an exception will be thrown, and the test will stop there.
If the getTheBoolean() method returns false , the assertFalse() method will return normally. Otherwise an exception will be thrown, and the test will stop there.
Of course the above test will fail in either the assertTrue() or assertFalse() call, if the getTheBoolean() method returns the same value in both calls. One of the assertTrue() or assertFalse() calls will fail.
assertNull() + assertNotNull()
The assertNull() and assertNotNull() methods test a single variable to see if it is null or not null . Here is an example:
import org.junit.Test; import static org.junit.Assert.*; public class MyUnitTest < @Test public void testGetTheObject() < MyUnit myUnit = new MyUnit(); assertNull(myUnit.getTheObject()); assertNotNull(myUnit.getTheObject()); >>
The call to myUnit.getTheObject() is inlined in the assertNull() and assertNotNull() calls.
If the myUnit.getTheObject() returns null, the assertNull() method will return normally. If a non-null value is returned, the assertNull() method will throw an exception, and the test will be aborted here.
The assertNotNull() method works oppositely of the assertNull() method, throwing an exception if a null value is passed to it, and returning normally if a non-null value is passed to it.
assertSame() and assertNotSame()
The assertSame() and assertNotSame() methods tests if two object references point to the same object or not. It is not enough that the two objects pointed to are equals according to their equals() methods. It must be exactly the same object pointed to.
import org.junit.Test; import static org.junit.Assert.*; public class MyUnitTest < @Test public void testGetTheSameObject() < MyUnit myUnit = new MyUnit(); assertSame (myUnit.getTheSameObject(), myUnit.getTheSameObject()); assertNotSame(myUnit.getTheSameObject(), myUnit.getTheSameObject()); >>
The calls to myUnit.getTheSameObject() are inlined into the assertSame() and assertNotSame() method calls.
If the two references points to the same object, the assertSame() method will return normally. Otherwise an exception will be thrown and the test will stop here.
The assertNotSame() method works oppositely of the assertSame() method. If the two objects do not poin to the same object, the assertNotSame() method will return normally. Othersise an exception is thrown and the test stops here.
assertThat()
The assertThat() method compares an object to an org.hamcrest.Matcher to see if the given object matches whatever the Matcher requires it to match.
Matchers takes a bit longer to explain, so they are explained in their own text (the next text in this trail).
JUnit Assertions
Ассерты (asserts) — это специальные проверки , которые можно вставить в разные места кода. Их задача определять, что что-то пошло не так. Вернее, проверять, что все идет как нужно. Вот это “как нужно” они и позволяют задать различными способами.
С некоторыми ассертами ты уже сталкивался в коде выше. Первый из них – проверка объектов на равенство. Если объекты не равны — кинется исключение и тест будет провален.
Тут важен порядок сравнения , ведь JUnit в итоговом отчете напишет что-то типа “получено значение 1, а ожидалось 3”. Общий формат такой проверки имеет вид:
assertEquals(эталон, значение)
@Test public void whenAssertingEquality ()
6.2 Методы assertEquals, assertTrue, assertFalse
Ниже я приведу список самых популярных методов — ассертов. По их названиям вполне можно догадаться как они работают. Но все же напишу краткое пояснение:
assertEquals | Проверяет, что два объекта равны |
---|---|
assertArrayEquals | Проверяет, что два массива содержат равные значения |
assertNotNull | Проверяет, что аргумент не равен null |
assertNull | Проверяет, что аргумент равен null |
assertNotSame | Проверят, что два аргумента — это не один и тот же объект |
assertSame | Проверят, что два аргумента — это один и тот же объект |
assertTrue | Проверяет, что аргумент равен true |
assertFalse | Проверяет, что аргумент равен false |
Некоторые из этих методов кажутся излишними. Зачем использовать assertSame(a, b) , если можно просто написать assertTrue(a == b) ?
Все дело в том, что assert — это очень умный метод. Он делает много чего полезного и, в том числе, пишет в лог информацию об ошибке . В первом случае он напишет, что ожидался объект А, а получен объект Б. Во втором случае просто напишет, что ожидалось true .
Когда у тебя сотни тестов, особенно выполняемые на специальном тестовом сервере, то наличие детальных логов может быть суперполезным. Думаю,ты понимаешь, о чем я.
Пример сравнения массивов:
@Test public void whenAssertingArraysEquality() < char[] expected = ; char[] actual = "Junit".toCharArray(); assertArrayEquals(expected, actual); >
6.3 Метод assertAll
Как уже говорилось выше, метод assert не просто выполняет проверку, но и пишет в лог много информации о сравнимых объектах.
Допустим выполняется сравнение:
Address address = unitUnderTest.methodUnderTest(); assertEquals("Вашингтон", address.getCity()); assertEquals("Oracle Parkway", address.getStreet()); assertEquals("500", address.getNumber());
Но если один из параметров не совпадет, то проверки остальных не произойдет. А хотелось бы чтобы они все-таки произошли и их результаты записались в лог. Но при этом, если хотя бы одна проверка не прошла, то тест все-таки был провален.
Для этого есть специальный метод — assertAll() . В качестве первого аргумента он принимает комментарий, который нужно записать в лог, а дальше — любое количество функций-ассертов.
Вот как будет переписан наш пример с его помощью:
Address address = unitUnderTest.methodUnderTest(); assertAll("Сложный сценарий сравнение адреса", () -> assertEquals("Вашингтон", address.getCity()), () -> assertEquals("Oracle Parkway", address.getStreet()), () -> assertEquals("500", address.getNumber()) );
Тогда если адрес будет неправильный, в лог будет написано что-то типа:
Сложный сценарий сравнение адреса (3 failures) expected: but was: expected: but was: expected: but was:
6.4 Метод assertTimeout
Помнишь аннотацию @Timeout ? Она позволяла контролировать время выполнения всего метода. Но иногда бывает полезно задать ограничения на выполнения некоторой части кода внутри метода. Для этого можно использовать assertTimeout() .
В качестве первого параметра в него передается время, а в качестве второго — код (функция), который должен выполниться за указанное время. Пример:
@Test public void whenAssertingTimeout() < assertTimeout( ofSeconds(2), () -> < // пауза в одну секунду Thread.sleep(1000); >); >
У класса Assert есть 12 вариантов метода assertTimeout() . Если хочешь ознакомиться с ними подробнее, добро пожаловать в официальную документацию.
6.5 Метод assertThrows
Очень часто бывают ситуации, когда тебе нужно убедиться, что в определенной ситуации код кидает нужное исключение: определил ошибку и кинул нужное исключение. Это очень распространенная ситуация.
На этот случай есть еще один полезный метод assert — это assertThrows() . Общий формат его вызова имеет вид:
assertThrows(исключение, код)
По сути, он очень похож на метод assertTimeout() , только он проверяет, чтобы указанный код выкинул нужное исключение. Пример:
@Test void whenAssertingException() < Throwable exception = assertThrows( IllegalArgumentException.class, () -> < throw new IllegalArgumentException("Exception message"); >); assertEquals("Exception message", exception.getMessage()); >