4.2 Getting Started

4.2.1 Problem

You want to write unit tests with JUnit.

4.2.2 Solution

Create a subclass of junit.framework.TestCase. Each unit test is represented by a testXXX( ) method within the TestCase subclass.

4.2.3 Discussion

Example 4-1 shows an extremely simple test case. A test case is a subclass of TestCase and contains a collection of unit tests. Instances of TestCase are sometimes referred to as test fixtures, although we prefer to say "test case" since that matches the class name. Each unit test is a public, no-argument method beginning with "test". If you do not follow this naming convention, JUnit will not be able to locate your test methods automatically. Instead, you would have to write a suite( ) method and construct instances of your test case, passing the test method name to the constructor.

Example 4-1. Simple test case
package com.oreilly.javaxp.common;

import junit.framework.TestCase;

/**
 * Sample unit tests for the {@link Person} class.
 */
public class TestPerson extends TestCase {

    /**
     * This constructor is only required in JUnit 3.7 and earlier.
     * @param testMethodName the name of the test method to execute.
     */
    public TestPerson(String testMethodName) {
        super(testMethodName);
    }

    /**
     * A unit test to verify the name is formatted correctly.
     */
    public void testGetFullName(  ) {
        Person p = new Person("Aidan", "Burke");
        assertEquals("Aidan Burke", p.getFullName(  ));
    }

    /**
     * A unit test to verify that nulls are handled properly.
     */
    public void testNullsInName(  ) {
        Person p = new Person(null, "Burke");
        assertEquals("? Burke", p.getFullName(  ));

        // this code is only executed if the previous assertEquals passed!
        p = new Person("Tanner", null);
        assertEquals("Tanner ?", p.getFullName(  ));
    }
}

In JUnit 3.7 and earlier, the constructor is required and must have the signature shown in the TestPerson class. JUnit uses this constructor to create a new instance of the test case as it runs each of the unit test methods. The name argument matches the current unit test's method name, allowing JUnit to use reflection to invoke the corresponding method. JUnit 3.8 removed the need for this constructor, so we will not include it in the remaining examples in this chapter.

The "test" methods are the actual unit tests. You must have at least one unit test in each test case or JUnit reports an error. Our TestPerson class has two unit tests, each of which checks different aspects of the Person class's getFullName( ) method. Test methods should[2] follow this signature:

[2] You could adopt a different naming convention; however, JUnit would not automatically find your test methods. You would have to build your test suite manually by constructing instances of your test case, passing your method names to the constructor.

public void test<something>(  ) [throws SomeException]

This naming convention allows JUnit to locate unit tests by reflection. Tests may throw any subclass of java.lang.Throwable. When this happens, JUnit catches the exception and reports a test error. It continues to execute any additional test methods.

Each unit test uses various assertXXX( ) methods to do the actual testing:

assertEquals("Aidan Burke", p.getFullName(  ));

This method confirms that its two arguments are equal. If the arguments are equal, the test passes. Otherwise, a test failure is reported and the remainder of the current test method is skipped. JUnit does proceed to execute other test methods, however. In the case of Object arguments (such as two Strings), the .equals( ) method is used for checking equality.

To compile TestPerson, include junit.jar in your classpath. The next recipe shows how to run the tests.

4.2.4 See Also

Recipe 4.3 shows how to run your tests. Recipe 4.4 explains the assert( ) methods. Recipe 4.5 describes how fine-grained your tests should be.