A complete guide to JUnit5 Assertions
|Assertions are the statements that are used to assert conditions in tests.
In this article, we will go through different methods that are present in the Assertions( in JUnit5) class.
All the methods in Assertions class are static and for the readability purpose it is recommended to static import all methods of Assertions.class
1. Why Assertions?
Basically, assert statements are the ones that give final meaning to a test method. Whenever we write a test, assert statements make it either a success or fail.
Also assert statements describe what exactly we are expecting from this test setup, whether we want two objects to be equal or whether an object is null or not, or whether a condition is true or false.
All these methods have a lot of overloaded methods for different data types like int, double, String, char, boolean, Object etc. It also depends on the number of parameters required for an assertion type.
For example, a minimum of two parameters is required for assertEquals, while for assertTrue minimum number of parameters required is only one..
But the basic overload structure has mainly three variations, one with a minimum number of params required, the second with an additional failure reason message, and the third one with an additional failure message supplier.
assertEquals(Object expected, Object actual) assertEquals(Object expected, Object actual, String message) assertEquals(Object expected, Object actual, Supplier<String> messageSupplier)
Lets implement the different assert methods and explore how we can use them.
2. assertEquals and assertNotEquals
assertEquals
is used to verify that two objects are equal.
assertNotEquals
is used to verify that two objects are not equal.
One important point is that we should always implement equals and hashCode when we want to test the equality of two custom Objects, else it might not work as expected.
@Test void testAssertEqualAndNotEquals() { var expected = "codingeek"; var actual = "codingeek"; assertEquals(expected, actual); assertNotEquals("Some random string", actual); }
3. assertArrayEquals
assertArrayEquals
is used to check the equality of two arrays.
We have to make sure that the elements in both the arrays are in the same order.
@Test void testAssertArrayEqual() { var expected = new char[]{'c','o','d','i','n','g','e','e','k'}; var actual = "codingeek".toCharArray(); assertArrayEquals(expected, actual); }
Note: If both the array objects are null then they are considered equal.
@Test void testAssertArrayEqual() { var expected = null; var actual = null; assertArrayEquals(expected, actual); }
4. assertNotNull and assertNull
We use assertNotNull
when we want to test that an object is not null.
Similarly, assertNull
is used to assert that an object is null.
@Test void testAssertNullAndNotNull() { String nullObject = null; var nonNullObject = "codingeek"; assertNull(nullObject); assertNotNull(nonNullObject); }
5. assertNotSame and assertSame
We use assertNotSame
to test that variables do not refer to the same object.
Similarly, assertSame
is used to assert that they refer to the same object.
@Test void testAssertSameAndNotSame() { var expectedObject = new Object(); var sameObject = expectedObject; assertSame(expectedObject, sameObject); var notSameObject = new Object(); assertNotSame(sameObject, notSameObject); }
Note: With assertSame we test the reference of the objects and with assertEquals we check the values in the object and that is the main difference between the two and same for assertNotSame and assertNotEquals.
6. assertTrue and assertFalse
We use assertTrue
to assert that the boolean variables is true.
Similarly, assertFalse
is used to assert that the boolean variables is false.
@Test void testAssertTrueAndFalse() { assertTrue(2 < 3); assertFalse(2 > 3); }
7. assertIterableEquals
assertIterableEquals
verifies that two iterables are equal with a deep comparison i.e. they both should return the objects in the same order.
It is independent of the object type these iterables are generated from.
If both the iterables are null then also they are considered equals.
So let’s try implementing iterables generated from List and a Set which generates the elements in the same order.
@Test void testAssertIterableEquals() { var listIterable = new ArrayList<>(Arrays.asList("a", "b", "c")); var setIterable = new LinkedHashSet<>(Arrays.asList("a", "b", "c")); assertIterableEquals(listIterable, setIterable); assertIterableEquals(null, null); }
8. assertLinesMatch
assertLinesMatch
matches and assert the expected and the actual String list.
But this method has a slight difference than other assertion methods in the class. It does 3 level of validations to test the list of Strings.
For each pair of expected and actual lines it checks –
- if expected.equals(actual) – if yes, then this is valid and moves to the next pair of lines
- otherwise it treats the expected String as a regular expression and check via String.matches(String) – if yes, then this is valid and moves to the next pair of lines
- otherwise check if expected line is a fast-forward marker, if yes apply fast-forward actual lines accordingly and goto 1.
A fast forward marker is an extended line that has >> at the beginning and end of the String. Examples –
- >> We should not test this line >>
- >> 5 >> – This is a special case as it says skip 5 lines.
@Test void testAssertLinesMatch() { var expectedList = new ArrayList<>(Arrays.asList("a", "\\d+", "[a-z]*")); var actualList = new ArrayList<>(Arrays.asList("a", "100", "codingeek")); assertLinesMatch(expectedList, actualList); assertLinesMatch(expectedList.stream(), actualList.stream()); }
9. assertAll
assertAll
verifies that all the executables run without throwing any error.
In case of multiple executables, if any executables throws exception it will continue to run all the other executables, consolidates the exceptions and report all of them at once.
The heading passed will be included in error message.
@Test void testAssertAll() { assertAll("Sitename", () -> assertTrue("Codingeek".startsWith("C")), () -> assertTrue("Codingeek".endsWith("k")), () -> assertEquals(9, "Codingeek".length()) ); }
In case of irrecoverable error like OutOfMemory error it will stop the execution.
10. assertTimeout
assertTimeout
succeeds only if the supplied executable completes the execution within the given timeout duration.
This method executes in the same thread and hence waits for the executable to finish the operation. If we want to finish test without waiting for the executable to finish then we should use assertTimeoutPreemptively
.
@Test void testAssertTimeoutNotExceeded() { // Does not fail as the method returns in less than a second assertTimeout(Duration.ofSeconds(1), () -> "Codingeek.com"); } @Test void testAssertTimeoutFailure() { // Does fails as the method does not returns in less than a second // Total running time for this method is a bit more than 2000 milliseconds assertTimeout(Duration.ofSeconds(1), () -> Thread.sleep(2000)); }
11. assertTimeoutPreemptively
assertTimeoutPreemptively
succeeds only if the supplied executable completes the execution within the given timeout duration.
The only difference from assertTimeout is that here the executable runs in a separate thread and hence it does not wait for the executable to complete the execution.
@Test void timeoutExceededWithPreemptiveTermination() { // This test fails but it fails in around 10 milliseconds only assertTimeoutPreemptively(Duration.ofMillis(10), () -> { Thread.sleep(5000); });
12. assertThrows and assertDoesNotThrow
assertThrows
asserts that the supplied executable throws the exception of the expected type.
Similarly, assertDoesNotThrow
asserts that the supplied executable does not throw any exception.
@Test void testAssertThrows() { Throwable throwable = assertThrows( ArithmeticException.class, () -> { var number = 10 / 0; }); assertEquals("/ by zero", throwable.getMessage()); } @Test void testAssertDoesNotThrow() { assertDoesNotThrow(() -> {}); }
13. fail
If we want to fail a test on some condition then we can use fail
method. Calling this method results in AssertionFailedError.
@Test void testFail() { var returnValue = (int) (Math.random() * 100); if (returnValue % 2 == 0) { fail("This value should be odd"); } }
14. Conclusion
In this article we have discussed all the different static methods that Assertions class provide in JUnit5.
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!! ?