JUnit is an open source Unit Testing Framework for JAVA. JUnit is a simple framework to write repeatable tests. It is an instance of the xUnit architecture for unit testing frameworks.
JUnit5 contains the assertions available as in JUnit 4 Assertions as well there are a few additional new asserts too. In this post, let’s discuss each new assertion in JUnit5 works in detail with examples.
1. assertIterableEquals
The assertIterableEquals() asserts that the expected and the actual iterables are deeply equal. In order to be equal, both iterable must return equal elements in the same order and it isn’t required that the two iterables are of the same type in order to be equal.
Example 1 – In this example, the number of elements as well as the sequence of elements is in the same order in both Iterables. It is not mandatory to have Iterables of the same type, so we can see as one of the Iterable is ArrayList whereas another Iteratble is of type LinkedList.
As both Iterables do not have same number of elements, so the Assertion has failed.
Note:- There are no assertions like assertNotIterableEquals() or assertIterableNotEquals().
2. assertLinesMatch
This Assertion asserts that the expected list of Strings matches the actual list of String. This method differs from other assertions that effectively only check String.equals(Object), in that it uses the following staged matching algorithm: For each pair of expected and actual lines do a) check if expected.equals(actual) – if yes, continue with next pair b) otherwise treat expected as a regular expression and check via String.matches(String) – if yes, continue with the next pair c) otherwise check if an expected line is a fast-forward marker, if yes apply to fast-forward actual lines accordingly (see below) and goto 1.
Example 1 – In the below example, expected has a regular expression that matches with the elements of actual.
When we want to assert that execution of the supplied executable completes before the given timeout, we can use assertTimeout().
Example 1 – In the below example, assertTimeout() is 2 sec, which means the assertion should be completed within 2 secs. We are waiting for 1 sec and then perform the assertion.
@Test
void assertTimeoutPositive() {
int a = 4;
int b= 5;
assertTimeout(
ofSeconds(2),
() -> {
// code that requires less then 2 seconds to execute
Thread.sleep(1000);
}
);
assertEquals(9, (a + b));
}
As the assertion is within the specified time of assertTimeout(), the timeout assertion passes and the test passes.
Example 2 – In the below example, assertTimeout() is 2 sec whereas are waiting for 5 sec and then performing the assertion.
@Test
void assertTimeoutNegative() {
int a = 4;
int b= 5;
assertTimeout(
ofSeconds(2),
() -> {
// code that requires less then 2 seconds to execute
Thread.sleep(5000);
}
);
assertEquals(9, (a + b));
}
As the assertion is outside the specified time of assertTimeout(), so the test fails. The assertion fails with an error message similar to: “execution exceeded timeout of 2000 ms by 3010 ms”.
Example 3 – In the below example, the assertion is mentioned just after
The executable will be executed in the same thread as that of the calling code. Consequently, execution of the executable will not be preemptively aborted if the timeout is exceeded.
@Test
void assertTimeoutNegative1() {
int a = 4;
int b= 5;
assertTimeout(
ofSeconds(2),
() -> {
// code that requires less then 2 seconds to execute
Thread.sleep(5000);
assertEquals(10, (a + b));
}
);
}
This shows that the assertion assertEquals() is still executed after the timeout also.
5. assertTimeoutPreemptively()
This assertion works just like assertTimeout(). When we want to assert that the execution of the supplied executable completes before the given timeout, we can use assertTimeoutPreemptively(). The only difference is that here the executable will be executed in a different thread than that of the calling code, whereas in assertTimeout() the executable will be executed in the same thread as that of the calling code. Furthermore, execution of the executable will be preemptively aborted if the timeout is exceeded here as contrary to assertTimeout() where the executable will not be preemptively aborted.
@Test
void assertPreemptiveTimeoutNegative() {
int a = 4;
int b= 5;
assertTimeoutPreemptively(
ofSeconds(2),
() -> {
// code that requires less then 2 seconds to execute
Thread.sleep(5000);
assertEquals(9, (a + b));
}
);
}
In this post, We saw that JUnit Jupiter comes with many of the assertion methods that JUnit 4 has and adds a few that lend themselves well to being used with Java 8 lambdas. All JUnit Jupiter assertions are static methods in the org.junit.jupiter.api.Assertions class.
Grouped assertions in JUnit 5 help make your tests cleaner and more readable by allowing you to group related assertions together with a single failure message if any of them fail. This is particularly useful when you want to ensure that multiple conditions are true in a given test scenario.
JUnit 5 supports an additional Assertion feature called Grouped assertions. In JUnit4, when you have to assert let’s say – 3 different conditions, then you need to write 3 different assertions and they will be executed sequentially. Imagine, 2nd assertion fails, then the program stops there and will not go to the 3rd assertion. To overcome this problem, JUnit5 has a new assertion called Grouped assertion that execute all the conditions present within it using assertAll(), irrespective of the fact if any assertion fails or not and generate a consolidated report with all the failures. To be honest, I love this feature and use very frequently.
All JUnit Jupiter assertions are static methods. They come from class:
org.junit.jupiter.api.Assertions
What is JUnit5?
JUnit 5 is composed of several different modules from three different sub-projects.
The JUnit Platform serves as a foundation for launching testing frameworks on the JVM. It also defines the Test Engine API for developing a testing framework that runs on the platform.
JUnit Jupiter is the combination of the new programming model and extension model for writing tests and extensions in JUnit 5. The Jupiter sub-project provides a Test Engine for running Jupiter-based tests on the platform.
JUnit Vintage provides a Test Engine for running JUnit 3 and JUnit 4 based tests on the platform. It requires JUnit 4.12 or later to be present on the classpath or module path.
To use JUnit5, add the Junit5 maven dependency to the POM.xml
Example 1 – The following example demonstrates positive assertions using `assertAll()` in JUnit 5. All assertions in this example are of the same type, specifically `assertEquals()`, grouped within an `assertAll()` assertion. The heading parameter for this group of assertions is “GroupedAssertionsWithSameAssertionType”.
@Test
void allPositive1() {
assertAll(
"GroupedAssertionsWithSameAssertionType",
() -> assertEquals(8, 5+3, "8 is not sum of 5 and 3"),
() -> assertEquals("java", "JAVA".toLowerCase()),
() -> assertEquals(16,4*4,"16 is not product of 4 and 4")
);
}
Result
As all 3 assertions pass, so the final result passes.
Grouped Assertions with Different Assertion Types
Example 2 – The following example demonstrates using `assertAll()` in JUnit 5 to group assertions of different types – assertEquals(), assertNotNull and assertNotEquals() within a single test. It consists of the heading parameter with the value “GroupedAssertionsWithDifferentAssertionType”.
@Test
void allPositive2() {
String str ="Spring";
assertAll(
"GroupedAssertionsWithDifferentAssertionType",
() -> assertEquals(8, 5+3, "8 is not sum of 5 and 3"),
() -> assertNotNull(str, () -> "The string should be null"),
() -> assertEquals("java", "JAVA".toLowerCase()),
() -> assertNotEquals(20,5*3,"20 is product of 5 and 3")
);
}
Result
As all 3 assertions pass, so the final result passes.
Grouped Assertions with multiple failure
Example 3– In the below example, out of 4 assertions, 3 assertions are failing, so the output will have the detail about all 3 assertion errors.
@Test
void allNegative() {
String str ="Spring";
Iterable<String> iterat1 = new ArrayList<>(asList("Java", "Junit4", "Test"));
Iterable<String> iterat2 = new ArrayList<>(asList("Java", "Junit5", "Test"));
assertAll(
"Negative-GroupedAssertionsWithDifferentAssertionType",
() -> assertIterableEquals(iterat1, iterat2),
() -> assertNull(str, () -> "The string should be null"),
() -> assertEquals("java", "JAVA"),
() -> assertNotEquals(20,5*3,"20 is product of 5 and 3")
);
}
Result
As one of the asserts in the group fails, instead of AssertionFailureErrorit results in MultipleFailuresError thereby displaying the heading of the grouped assertion passed as the input parameter i.e. Negative-GroupedAssertionsWithDifferentAssertionType in this example. This image shows all the 3 assertion failures.
Assertion 1 fails as we were expecting JUnit4, but response has JUnit5 Assertion 2 fails as the string was not NULL. Assertion 3 fails as Java is not equal to JAVA (case sensitivity).
Grouped Assertions Without Heading As Parameter
Grouped Assertions with Same Assertion Type
The assertAll () can be implemented without using the heading parameter. The below example is the same as the above one, we are just skipping the heading part.
@Test
void allNegative() {
String str ="Spring";
Iterable<String> iterat1 = new ArrayList<>(asList("Java", "Junit4", "Test"));
Iterable<String> iterat2 = new ArrayList<>(asList("Java", "Junit5", "Test"));
// In a grouped assertion all assertions are executed, and all failures will be reported together
assertAll(
() -> assertIterableEquals(iterat1, iterat2),
() -> assertNull(str, () -> "The string should be null"),
() -> assertEquals("java", "JAVA"),
() -> assertNotEquals(20,5*3,"20 is product of 5 and 3")
);
}
Result
The result displays without a heading.
Nested Or Dependent Grouped Assertions
Example with Outer assertAll() Passing and Nested assertAll() Executing
When one assertAll() includes one or more assertAll() then these are referred to as Nested or Dependent grouped assertions.
Example 1 – In this case, first, the assertAll() validates if the sum is correct or not. The sum is correct here, so the control moves to the nested assertAll() to verify all the assertions present within it.
@Test
void allDependentPositive() {
String str ="Spring";
// Within a code block, if an assertion fails the subsequent code in the same block will be skipped.
assertAll(
"DependentPositiveAssertions",
() -> {
assertEquals(8, 5 + 3, "8 is not sum of 5 and 3");
// Executed only if the previous assertion is valid.
assertAll("sub-heading",
() -> assertNotNull(str, () -> "The string should be null"),
() -> assertEquals("java", "JAVA".toLowerCase()),
() -> assertEquals(20, 5 * 4, "20 is product of 5 and 4")
); // end of inner AssertAll()
}
); // end of outer AssertAll()
}
Result
All the assertions within nested assertAll() are passes. So the final result passes.
Example of Outer AssertAll() Causing Nested AssertAll() Not to Execute
Example 2– In the below example, outer AssertAll() fails, so all the assertions within nested/dependent assertAll() are not executed.
@Test
void allDependentNegative() {
String str ="Spring";
// Within a code block, if an assertion fails the subsequent code in the same block will be skipped.
assertAll(
"DependentPositiveAssertions",
() -> {
assertEquals(8, 5 + 4, "8 is not sum of 5 and 3");
// Executed only if the previous assertion is valid.
assertAll("sub-heading",
() -> assertNull(str, () -> "The string should be null"),
() -> assertNotEquals("java", "JAVA".toLowerCase()),
() -> assertNotEquals(20, 5 * 4, "20 is product of 5 and 4")
); // end of inner AssertAll()
}
); // end of outer AssertAll()
}
Result
Example of Outer AssertAll() allows Nested AssertAll(), but nested AssertAll fails
Example 3 – In the below example, outer AssertAll() passes, so all the assertions within nested/dependent assertAll() are executed. But due to the failure of assertNull, the nested assertions are not evaluated, and the report will indicate the failure of `assertNull` first
@Test
void allDependentNegative1() {
String str ="Spring";
// Within a code block, if an assertion passes the subsequent code in the same block will be executed.
assertAll(
"DependentNegativeAssertions",
() -> {
assertEquals(8, 5 + 3, "8 is not sum of 5 and 3");
// Executed only if the previous assertion is valid.
assertAll("sub-heading",
() -> assertNull(str, () -> "The string should be null"),
() -> assertNotEquals("java", "JAVA".toLowerCase()),
() -> assertNotEquals(20, 5 * 4, "20 is product of 5 and 4")
); // end of inner AssertAll()
}
); // end of outer AssertAll()
}
Result
The nested assertions have failed. So they can be seen in the execution status.
In short,
When first assertAll() method passes, then all the subsequent assertions within that block will be executed and these assertions can further pass or fails.
When the first assertAll() assertion fails, then the execution of subsequent assertions is skipped.
That’s it! Congratulations on making it through this tutorial and hope you found it useful! Happy Learning!!