An assertion is a predicate used to verify a programmer assumption (expectation) with an actual outcome of a program implementation. For example, a programmer can expect that the addition of two positive numbers will result in a positive number. So, the programmer can write a program to add two numbers and assert the expected result with the actual result.
The org.junit.Assert
package provides static overloaded methods for asserting expected and actual values for all primitive types, objects, and arrays.
This section covers the proper usage of the Assertion
APIs. The following are the best practices.
Use the correct assertion method. JUnit supports many assertion options, such as assertEquals
, assertTrue
, assertFalse
, assertNull
, assertNotNull
, assertSame
, and assertThat
. Use the most appropriate one. The following are the examples:
assertTrue(yourClass.someMethod())
instead of using assertEquals(true, yourClass.someMethod())
assertFalse(yourClass.someMethod())
instead of calling assertTrue(!yourClass.someMethod())
assertNull(yourClass.someMethod())
rather than assertEquals(null, yourClass.someMethod())
assertEquals(expected, yourClass.someMethod())
instead of using assertTrue(expected.equals(yourClass.someMethod()))
assertThat(age, is(30))
method is more readable than assertEquals(30, age)
assertThat(age, is(not(33)))
is more readable than assertTrue(age != 33)
The
assertEquals
method is a very useful method to verify the expectation. The assertEquals
method has the assertEquals(Object expected, Object actual)
signature.
Maintain the parameter order: first the expected value and then the actual result. The following JUnit snippet reverses the order, passes the actual value first, and then the expected result:
@Test public void currencyRoundsOff() throws Exception { assertEquals(CurrencyFormatter.format(100.999), "$101.00"); }
When the test fails, the error message says that the expected value is 101,00 € but actually the expected value is $101.00.
So, assertEquals
shows misleading error messages when the parameter order changes.
The following screenshot shows the error message. It says the test expects euros (€) but receives dollars ($):
Optionally, you can pass a meaningful message to assertEquals
to describe the cause. The assertEquals(String message, Object expected, Object actual)
signature takes a String
message to display a meaningful error message when the actual value doesn't match the expected value.
The following JUnit snippet passes a meaningful error message:
@Test public void currencyRoundsOff() throws Exception { assertEquals("Currency formatting failed", $101.00", CurrencyFormatter.format(100.999)); }
The following is the Assertion
failure output with an informative message:
Strive for one assertion per test method. When you check one assertion per test and a unit test fails, it is much easier to determine what went wrong. When a unit test has more than one assertion, and one assertion fails, extra effort is required to determine which one failed; for one assertion per test, no extra effort is required.
When a unit test performs more than one assertion, and a runtime exception is thrown, the assertions after the exception do not get verified; the JUnit framework marks the unit test as erroneous and proceeds to the next test method.
The following JUnit test asserts three conditions—the formatted amount is not null, the formatted amount contains a $ symbol, and the exact formatting:
@Test public void currencyRoundsOff() throws Exception { assertNotNull(CurrencyFormatter.format(100.999)); assertTrue(CurrencyFormatter.format(100.999).contains("$")); assertEquals("$101.00", CurrencyFormatter.format(100.999)); }
When any assertion fails, the output doesn't tell you what is wrong (you get the line number in the source code file, though, it is not very convenient to work with). The following is the JUnit output:
Instead of using three assertions, you can create three tests, or you can pass meaningful error messages to the assertion methods. The following JUnit test is modified to pass error messages:
@Test public void currencyRoundsOff() throws Exception { assertNotNull("Currency is NULL", CurrencyFormatter.format(100.999)); assertTrue("Currency is not USD($)", CurrencyFormatter.format(100.999).contains("$")); assertEquals("Wrong formatting", "$101.00", CurrencyFormatter.format(100.999)); }
Now, the failing test gives you additional information about the failure. The following is the test output. It reads Currency is not USD($), which means the second assertion failed: