This is an in-depth tutorial on JUnit Assertions with practical examples. We will also see the differences between assertSame vs assertEquals:
In this tutorial, we will explore one of the predominant aspects of JUnit API i.e. Introduction to JUnit Assertions both in JUnit 4 vs JUnit 5.
=> Check ALL JUnit Tutorials Here
Table of Contents:
JUnit Assertions
Assertions is a JUnit API or library of functions through which you can verify if a particular logic or condition returns true or false after execution of the test. If it returns false, then an AssertionError is thrown.
This is the best feature that helps in effective unit testing. In other words, assertion helps us to validate the expected output with the actual output for a specific test case.
Advantages Of Using Assertions
- Writing assertions is one of the fastest and most effective ways to detect and fix bugs.
- It helps you to get confidence that your assumptions on the output of a particular condition are correct.
- Sometimes assertions work as a precondition for a function call or could be a postcondition too.
Implementation Of JUnit Assertions
Deep diving into the actual implementation of Assertions, both JUnit 4 and JUnit 5 have different classes that contemplate various assert methods each serving its own unique purpose.
JUnit 4 has all the assert methods under the Assert class while JUnit 5 has all the assert methods under the Assertions class.
The package for JUnit 5 to be imported is org.junit.jupiter.api. Assertions and for JUnit 4 it is
org. junit. Assert
#1) JUnit 4 – Assertions
Reference => JUnit 4 Static Assert Methods
#2) JUnit 5- Assertions
Reference => JUnit 5 Assert Methods
#3) Implementation Of JUnit 4 – Assertions
Here on, let’s understand the implementation of each of the significant assert methods from the Assert class.
Example for: static void fail (String message):
package ordertests.com; import static org. junit. Assert. *; import org. junit. Test; public class JUnit4Assertion1 { @Test public void test () { fail ("Failing the testcase deliberately"); } }
Result: The testcase fails with an AssertionError displaying the message passed as the parameter.
Examples for static void assertEquals (String message, double expected, double actual, double delta):
Example 1: The below code has expected and actual values within a difference of positive delta value, hence test passes despite expected and actual are not exactly equal. In the below example, if the delta ranges from (3-1) =2 or more then the test passes.
package ordertests.com; import static org. junit. Assert. *; import org. junit. Test; public class JUnit4Assertion1 { @Test public void test () { int a=1; int b=3; int delta=2; assertEquals ("assert if value: "+a+ " is equal to "+b+ " with a difference of positive delta value:"+delta, a, b, delta); } }
Result:
Example 2: The below code snippet doesn’t have expected and actual values within a difference of the delta value, hence the test fails. In the below example, if the delta is less than (3-1) =2 then the test fails with an AssertionError displaying the String message passed as the input parameter.
package ordertests.com; import static org. junit. Assert. *; import org. junit. Test; public class JUnit4Assertion1 { @Test public void test () { int a=1; int b=3; int delta=2; assertEquals ("assert if value: "+a+ " is equal to "+b+ " with a difference of positive delta value:"+delta, a, b, delta); } }
Result:
Example 3: When bypassing delta value, if you still want to verify the exact match between the expected and actual value then keep the delta value =0. In the below example a=1, b=1 and delta=0. Since the difference between the actual and expected value is 0, the test passes.
public class JUnit4Assertion1 { @Test public void test() { int a=1; int b=1; int delta=0; assertEquals ("Value: "+a+ " is not equal to "+b+ " with a difference of positive delta value: "+delta, a, b, delta); } }
Result:
Examples for: static void assertFalse (boolean condition)
Example 1: assertFalse verifies if the condition results in boolean value False. In this example, the condition returns false hence the test passes.
package ordertests.com; import static org. junit. Assert. *; import org. junit. Test; public class JUnit4Assertion1 { @Test public void test() { int a=5; boolean flag; if(a<2) { flag=true; } else { flag=false; } assertFalse (flag); } }
Result:
Example 2: The test fails with AssertionError when the condition in the input parameter returns true. In the below example, the condition returns true hence the test fails.
public class JUnit4Assertion1 { @Test public void test() { int a=1; boolean flag; if(a<2) { flag=true; } else { flag=false; } assertFalse (flag); } }
Result:
Example for: static void assertNotNull (String message, Object object)
Example 1: In the below example, the object is null hence the test fails.
package ordertests.com; import static org. junit. Assert. *; import org. junit. Test; public class JUnit4Assertion1 { @Test public void test() { String newStr=null; assertNotNull ("The object newStr is null", newStr); } }
Result:
Example 2: In the below example, the object is not null hence the test passes.
public class JUnit4Assertion1 { @Test public void test() { String newStr="newStr"; assertNotNull ("The object newStr is null", newStr); } }
Result:
Example for: static void assertArrayEquals (String message, char [] expecteds, char [] actuals)
The method assertArrayEquals() uses an array of character values of expected vs actual values and validates if they match. Even if both expected and actual are null, the test passes.
In the below example, since the actual and expected values of the character array do not match, the test fails to display the string message passed as an input.
package ordertests.com; import static org. junit. Assert. AssertArrayEquals; import org. junit. Test; public class JUnit4Assertion1 { @Test public void verifyEqualCharValues() { char [] actualChar= {'H','O','M','E'}; char [] expectedChar={'h','o','m','e'}; assertArrayEquals ("Assertion failed as the two values didn’t match”, expectedChar, actualChar); } }
Result:
#4) Difference Between assertEquals() Vs assertSame()
In this section, we will try to answer one of the very basic but genuine questions regarding the JUnit assertion – if assertEquals() validates that the two objects are equal and if assertSame() also validates if the two objects are the same then, why do we have two different functions for the same purpose?
The answer would seem really interesting to you. The explanation is here – assertEquals() uses equals() method to validate if the two objects are equal whereas assertSame() uses the operator == to validate if two objects are equal. Both of these approaches vary; hence the results are different as well.
Example 1: We will see how the assertEquals() work on the 2 string objects with the same values. We already know, that assertEquals() internally uses the equals() function to validate if two objects are equal. Hence, the below test passes as it validates if the object values are equal.
package ordertests.com; import static org. junit. Assert. *; import org. junit. Test; public class JUnit4Assertion1 { @Test public void test() { String s1 = new String("HELLO"); String s2 = new String("HELLO"); assertEquals ("the values are not equal", s1, s2); } }
Result:
Example 2: We will now see how the assertSame() works on the 2 string objects with the same values. The assertSame() internally uses operator == to validate if two objects are equal. Despite the two string values are the same, the below test fails. The reason being that the two object references are different.
Both the string objects s1 and s2 are referring to the different memory addresses that result in the failure of the assert function.
public class JUnit4Assertion1 { @Test public void test() { String s1 = new String("HELLO"); String s2 = new String("HELLO"); assertSame ("the values are not equal", s1, s2); } }
Result:
Example 3: In this example, we will pass the same string values instead of the String class object and see how differently it works. Here, the test passes.
public class JUnit4Assertion1 { @Test public void test() { assertSame ("the values are not equal", "HELLO", "HELLO"); } }
Result:
static imports in JUnit
The static imports are an additional feature in JUnit using which the static methods under the class can be called without using the class name with it.
With static import:
Using static import with JUnit class Assert, there is no need to include Assert.assertSame() or Assert. With any of its static assertion methods for that matter. This gives easy and shorter access to the method calls.
package ordertests.com; import static org. junit. Assert. *; import org. junit. Test; public class JUnit4Assertion1 { @Test public void test () { assertSame ("the values are not same", "str1", "str11"); } }
Without static import:
In this example, we see that there is no “static” keyword used in the import statement of the Assert class which is why all the assert methods will need to be used in the pattern Assert dot assert method (e.g. Assert.assertSame())
package ordertests.com; import org. junit. Assert; import org. junit. Test; public class JUnit4Assertion1 { @Test public void test () { Assert.assertSame ("the values are not same", "str1", "str11"); } }
Advantage of static import:
The advantage of having static import for the Assert class is:
- To eliminate the redundant usage of the Assert class name with the assert methods.
- It saves time.
- Makes typing better and
- Improves the readability of the code.
#5) Implementation Of JUnit 5- Assertions
Here on, we shall learn about the implementation of various assert methods under the Assertion class.
Examples for assertEquals (float expected, float actual, float delta, String message):
Example 1: The below code has expected and actual values within a difference of positive delta value, hence test passes despite expected and actual are not exactly equal. In the below example, if the delta ranges from (3.2-1.2) =2 or more then the test passes.
package junit5assert; import static org.junit.jupiter.api. Assertions. *; import org.junit.jupiter.api. Test; class JUnit5Assertion1 { @Test void test () { float a=(float) 1.2; float b=(float) 3.2; float delta=(float) 2.1; assertEquals (a, b, delta, “assert if value: "+a+ " is equal to "+b+ " with a difference of positive delta value:"+delta); } }
Result:
Example 2: The below code doesn’t have expected and actual values within a difference of the delta value, hence the test fails. In the below example, if the delta is less than (3.2-1.2) =2 then the test fails with an AssertionError displaying the String message passed as the input parameter.
class JUnit5Assertion1 { @Test void test () { float a=(float) 1.2; float b=(float) 3.2; float delta=(float) 1; assertEquals (a, b, delta, “assert if value: "+a+ " is equal to "+b+ " with a difference of positive delta value:"+delta); } }
Result:
Examples for: static void assertFalse (boolean condition, String message)
Example 1: assertFalse verifies if the condition results in boolean value False. In this example, the condition returns false hence the test passes.
package junit5assert; import static org.junit.jupiter.api. Assertions. *; import org.junit.jupiter.api. Test; class JUnit5Assertion1 { @Test void test () { int a=5; boolean flag; if(a<2) { flag=true; } else { flag=false; } assertFalse (flag, “Flag is true hence assert is failed"); } }
Result:
Example 2: The test fails with an AssertionError displaying the string message passed as an input parameter when the condition in the input parameter returns true. In the below example, the condition returns true hence the test fails.
class JUnit5Assertion1 { @Test void test () { int a=1; boolean flag; if(a<2) { flag=true; } else { flag=false; } assertFalse (flag, “Flag is true hence assert is failed"); } }
Result:
Example for: static void assertNull (Object actual, Supplier<String> messageSupplier):
Example 1: In the below example, the object is null hence the test passes with the Supplier message provided as an input parameter. Please observe the implementation of the message under the Supplier type. Supplier is imported from java. function.Supplierpackage.
package junit5assert; import static org.junit.jupiter.api. Assertions. *; import java. util. function. Supplier; import org.junit.jupiter.api. Test; class JUnit5Assertion1 { @Test void test () { String myStr=null; Supplier<String> strSupplier = () -> new String ("The object is null hence assert is failed"); String myAssertMsg = strSupplier.get (); assertNull (myStr, myAssertMsg); } }
Result:
Example 2: In the below example, the object is not null hence the test fails to display the Supplier type message.
class JUnit5Assertion1 { @Test void test () { String myStr="This string is not null"; Supplier<String> strSupplier = () -> new String ("The object is null hence assert is failed"); String myAssertMsg = strSupplier.get (); assertNull (myStr, myAssertMsg); } }
Result:
Examples for: assertArrayEquals (char [] expected, char [] actual, String message)
The method assertArrayEquals () uses an array of character values of expected vs actual values and validates if they match. Even if both expected and actual are null, the test passes.
In the below example, since the actual and expected values of the character array match, the test passes.
package junit5assert; import static org.junit.jupiter.api. Assertions. *; import org.junit.jupiter.api. Test; class JUnit5Assertion1 { @Test public void verifyEqualCharValues () { char [] actualChar= {'H','O','M','E'}; char [] expectedChar= "HOME”. toCharArray (); assertArrayEquals (expectedChar, actualChar); } }
Result:
Examples for: assertIterableEquals (Iterable<?> expected, Iterable<?> actual, String message)
The method assertIterableEquals () validates a list of expected values vs actual values belonging to the Iterable Interface.
The rules for this type of assert are as follows:
- Both the Iterable values must be exactly the same or call it equal and must be in the same order as well.
- Both Iterable types can differ.
Example 1: In the below example, the expected and actual List both are of type ArrayList however the value ‘Second’ from the expectedList didn’t match with value ‘Two’ in the actual List hence the test failed.
package junit5assert; import static org.junit.jupiter.api. Assertions. *; import java. util. ArrayList; import java. util. Arrays; import org.junit.jupiter.api. Test; class JUnit5Assertion1 { @Test public void verifyIterablesValueMatch () { Iterable<String> expectedList = new ArrayList<> (Arrays.asList("First", "Second", "Third")); Iterable<String> actualList = new ArrayList<> (Arrays.asList("First", "Two", "Third")); assertIterableEquals (expectedList, actualList); } }
Result:
Example 2: In the below example, the expected List is of type LinkedList and the actual List is of type ArrayList where both the lists return equal elements and in the same order. Hence, the test passes.
class JUnit5Assertion1 { @Test public void verifyIterablesValueMatch () { Iterable<String> expectedList = new LinkedList<>(Arrays.asList("First", "Second", "Third")); Iterable<String> actualList = new ArrayList<> (Arrays.asList("First", "Second", "Third")); assertIterableEquals(expectedList, actualList); } }
Result:
Examples for: static void assertLinesMatch(List<String> expectedLines, List<String> actualLines)
The assert method assertLinesMatch() validates if the expected vs actual pair of lines of String matches. However, it works with the approach of using String.equals(object) and String.matches(String).
The algorithm used in assertLinesMatch() is as below:
- If the expected value matches against the actual value on internally applying the .equals() method then the next pair of expected and actual values are picked up for verification.
- If .equals() doesn’t provide a pass over the match of the values, the code checks if the regular expression is provided and it applies the .matches() function which in turn validates if the regular expression provided for the expected value results into a pass when matched against the actual value. If yes, the next pair of expected and actual values are picked for validation.
- If .matches() also doesn’t result in a pass, then it checks if there is a fast forward marker in the expected value and validates it. Fast forward marker is a literal which starts and ends with >> and atleast 4 characters need to be passed.
Example 1:
In the below example, the first and the second pair passes with the match of a regular expression, and the third pair matches with .equals(). The final test result passes.
package junit5assert; import static org.junit.jupiter.api.Assertions.*; import java. util.Arrays; import java.util.List; import org.junit.jupiter.api.Test; class JUnit5Assertion1 { @Test public void verifyLinesMatch () { List<String> expected = Arrays.asList(“. *",”. *", "house"); List<String> actual = Arrays.asList("This is a ", "beautiful", "house"); assertLinesMatch(expected, actual); } }
Result:
Example 2:
In the below example, the first and second pair of lines are skipped as the check is with the third approach of fast forward marker >>2>> and the third pair is matched with the .equals() function. Hence, finally, the test passes.
class JUnit5Assertion1 { @Test public void verifyLinesMatch () { List<String> expected = Arrays.asList(">>2>>","house"); List<String> actual = Arrays.asList("This is a ", "beautiful", "house"); ha (expected, actual); } }
Result:
Example 3: In the below example, the first pair is matched using the fast forward marker >>1>> where the 1st pair of the line is skipped, the second and third pair are validated using .equals() however the test fails as the second pair of values ‘new’ and ‘beautiful’ do not match.
class JUnit5Assertion1 { @Test public void verifyLinesMatch() { List<String> expected = Arrays.asList(">>1>>","new”, “house"); List<String> actual = Arrays.asList("This is a ", "beautiful", "house"); assertLinesMatch (expected, actual); } }
Result:
Example 4: The expected value includes >>>> as a fast forward marker which skips all lines for validation. Hence, the test passes.
class JUnit5Assertion1 { @Test public void verifyLinesMatch () { List<String> expected = Arrays.asList(">>>>"); List<String> actual = Arrays.asList("This is a ", "beautiful", "house"); assertLinesMatch (expected, actual); } }
Result:
Example 5: In the below example, the expected value includes >>4>> as a fast forward marker that tries to skip 4 pairs of lines for validation. The test fails and displays AssertionError as the test has just 3 pairs of lines and the 4th pair of the line cannot be found.
class JUnit5Assertion1 { @Test public void verifyLinesMatch () { List<String> expected = Arrays.asList(">>4>>"); List<String> actual = Arrays.asList("This is a ", "beautiful", "house"); assertLinesMatch (expected, actual); } }
Result:
Conclusion
In this tutorial, we tried detailing the important aspect of JUnit which is Assertions. We understood various assert methods under JUnit 4 vs JUnit 5. Additionally, we also saw the implementation of most of the assert methods through various examples.
=> Read Through The Easy JUnit Training Guide Here