JUnit

Learn about JUnit and its features.

What is JUnit?

JUnit is a simple framework to write repeatable tests.

A typical JUnit 4.x test consists of multiple methods annotated with the @Test annotation.

At the top of every JUnit test class, we should include all the static Assert methods and annotations like so:

import static org.junit.Assert.*;
import org.junit.Test;
import org.junit.Before;
import org.junit.After;

Use the @Before to annotate initialization methods that are run before every test and @After to annotate break-down methods that are run after every test.

Each test method should test one thing, and the method name should reflect the test’s purpose. For example:

public void toStringYieldsTheStringRepresentation() {
       String[] array = {"a", "b", "c"};
       ArrayWrapper<String> arrayWrapper = new ArrayWrapper<String>(array);
       assertEquals("[a, b, c]", arrayWrapper.toString());
}

Hamcrest

In more recent versions (JUnit 4.4+), JUnit also includes Hamcrest matchers:

import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;

Then you can create more readable tests using the Hamcrest core-matchers. For example:

@Test
public void sizeIs10() {
     assertThat(wrapper.size(), is(10));
}

Assumptions

Often, there are variables outside of a test that is beyond your control. But the test assumes to be true. When an assumption fails, it shouldn’t necessarily mean the test fails. For this purpose, JUnit adds assumeThat, which you may import like so:

import static org.junit.Assume.*;

Then in our tests, we can verify assumptions before our assertions. For example:

assumeThat(File.separatorChar, is('/'));

When an assumption fails, the test is either marked as “passing” or “ignored,” depending on the version of JUnit.

Assumptions can be combined with either a Parameterized test or Theory to create tests that cover a wide variety of situations.

Parameterized tests

In testing, very often we want to test something with a wide variety of input values. Whether we call it a smoke test, white box, black box, or gray box testing, the testing solution remains the same. For this purpose, JUnit added the concept of a Parameterized test.

By using a few annotations, we can define a list of values to be used for multiple runs of the same tests.

/* imports... */
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameter;
import org.junit.runners.Parameterized.Parameters;

@RunWith(Parameterized.class) //1
public class BookTest {

        @Parameter public Integer number; //2

        @Parameters(name = "{index}: testForNumber({0})") //3
        public static List<Integer> getNumbers() {
               return Arrays.asList(1, 2, 3, 5, 10, 20, 49, 50, 51);
}
  • Add the @RunWith annotation, and specify the Parameterized test runner that should be used by this Test class.

  • Parameters should be declared public and annotated with @Parameter. If you prefer, you could add a constructor with parameters instead.

  • One method should be defined as public static and annotated with @Parameters and return a Collection or array of values to use as parameters. The name specified by this annotation will be used to label every execution of each test with {index} replaced by the index of parameters (starting at 0), and {#} replaced by the relevant parameter.

We can specify multiple parameters with the @Parameter annotation by including an index for each parameter as follows:

@Parameter(0) //1
public Integer number;
@Parameter(1) //2
public Boolean single;

@Parameters(name = "{index}: testFor({0}, {1})") //3
public static List getValues() {
       return Arrays.asList(new Object[][] {{1, true}, {2, false}});
}
  • Specify the first parameter with index zero.
  • Specify the second parameter.
  • Then, specify the format of the test name using those indexes.

We can provide multiple values for parameters by using a list of Object arrays as shown above. Finally, we can specify any number of tests annotated with @Test by using the defined parameters. By using assumptions, we can limit some tests to a subset of parameter values.

Get hands-on with 1200+ tech skills courses.