Working with assertions

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.

Using the correct assertion

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:

  • Use assertTrue(yourClass.someMethod()) instead of using assertEquals(true, yourClass.someMethod())
  • Use assertFalse(yourClass.someMethod()) instead of calling assertTrue(!yourClass.someMethod())
  • Use assertNull(yourClass.someMethod()) rather than assertEquals(null, yourClass.someMethod())
  • Use assertEquals(expected, yourClass.someMethod()) instead of using assertTrue(expected.equals(yourClass.someMethod()))
  • The assertThat(age, is(30)) method is more readable than assertEquals(30, age)
  • Similarly, assertThat(age, is(not(33))) is more readable than assertTrue(age != 33)

Maintaining the assertEquals parameter order

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 ($):

Maintaining the assertEquals parameter order

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:

Maintaining the assertEquals parameter order

Striving for one assertion per test

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:

Striving for one assertion per test

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:

Striving for one assertion per test
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset