All Courses
JUnit Tutorials

This JUnit tutorial will show you how to create and run tests in the unit test. Unit testing is a common method of test-driven development (TDD).
Java code can be unit tested using a code-driven unit testing framework. The following are some of the code-driven unit testing frameworks available in Java.

  1. SpryTest
  2. Jtest
  3. JUnit
  4. TestNG

JUnit is Java’s most popular and widely used unit testing framework. This allows developers to elegantly test their code. Apparently, TestNG is cleaner than JUnit, but JUnit is much more popular than TestNG. JUnit has excellent mock framework support like Mockito, which provides a custom JUnit 4 runner.

JUnit 4 is an annotation-based, flexible framework. The following are the advantages of JUnit 4 over its predecessor:

  • Instead of inheriting from junit.framework.Testcase, any class can be a test class. It doesn’t force you to extend the TestCase class.
  • The setUp and tearDown methods are replaced by the @before and @after annotations
  • Any public method annotated as @test can be a test method

Exploring annotations

1. @Test

The @Test annotation represents a test. Any public method can be annotated with the @Test annotation with @Test to make it a test method. There’s no need to start the method name with the test.

For Example:

@Test
  public void someTest2() {
     System.out.println(“\t\t someTest2 is invoked”);
   }

2. @Before and @After

JUnit4 provides @Before annotations. If you annotate a public void method with @Before, that method will be executed before each test run. JUnit 3 has a setUp () method for this purpose.
Similarly, methods annotated with @After are executed after each test method is executed. JUnit 3 has a tearDown () method for this purpose.

3. @BeforeClass and @AfterClass

JUnit 4 provides two annotations, @BeforeClass, and @AfterClass. These are only run once per test class. The @BeforeClass and @AfterClass annotations can be used with any public static void method. The @BeforeClass annotation runs before the first test and the @AfterClass annotation runs after the last test.
@Before and @After can be applied to any public void method. @AfterClass and @BeforeClass can only be applied to public static void methods.

Running the first unit test

Follow the steps below to create your first test.

1. To Create Test Class:

Create a test class under the test source package. Create a source folder called test and create a SanityTest.java Java class under the com.packtpub.junit.recap package.

JUnit TUTORIAL

We recommend that you use the test suffix to create your test class. Therefore, the MyClass class has a MyClassTest test class. Some code coverage tools ignore tests unless they end with a test suffix.

2. Add the following code to the SanityTest class:

import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
 
public class SanityTest {
  
  @BeforeClass
  public static void beforeClass() {
    System.out.println(“***Before Class is invoked”);
  }
 
  @Before
  public void before() {
    System.out.println(“____________________”);
    System.out.println(“\t Before is invoked”);
  }
  @After
  public void after() {
    System.out.println(“\t After is invoked”);
    System.out.println(“=================”);
  }
  
  @Test
  public void someTest() {
    System.out.println(“\t\t someTest is invoked”);
  }
  
  @Test
  public void someTest2() {
    System.out.println(“\t\t someTest2 is invoked”);
  }
  
  
  @AfterClass
  public static void afterClass() {
    System.out.println(“***After Class is invoked”);
  }
}

In the previous class, we created 6 methods. The two test methods are annotated with @Test. Note that the two methods (beforeClass and afterClass) are static and the other four are non-static. Static methods annotated with @BeforeClass are called only once before the test class is instantiated, and @AfterClass is called after the class has finished all execution.

3. Run the test:

Press Alt + Shift + X and T or navigate to Run | Run As | JUnit Test. You will see the following console (System.out.println) output:

JUnit TUTORIAL

Make sure the Before and After methods are executed before and after each test run. However, the order in which the test methods are executed may be different. For some runs, someTest can run before someTest2 or vice versa. The afterClass and beforeClass methods are executed only once.

Verifying test conditions with Assertion

An assertion is a tool (predicate) used to validate programming assumptions (expectations) with the actual results of program implementation. For example, a programmer might expect to add two positive numbers together to get a positive number. Therefore, he or she can write a program that adds two numbers and confirms the expected result in the actual result.
The org.junit.Assert package provides statically overloaded methods to assert expected and actual values ​​for all primitive types, objects, and arrays.

The following are the useful assert methods:

  • assertTrue (condition) or assertTrue (error message, condition): If the condition is false, the assertion fails and an AssertionError is thrown. If an error message is passed, an error message will be printed.
  • assertFalse (condition) or assertFalse (error message, condition): If the condition is true, the assertion fails and an AssertionError is thrown.
  • assertNull: This checks if the object is null, otherwise it throws an AssertionError if the argument is not null.
  • assertNotNull: Checks if the argument is not null. Otherwise, an AssertionError will be thrown.
  • assertEquals (string message, expected object, current object), or assertEquals (expected object, current object), or assertEquals (expected primitive, current primitive): This method is a primitive. It shows interesting behavior when you pass a value and then compare the values. When the object is passed, the equals () method is called. In addition, an AssertionError is thrown if the actual value does not match the expected value.
  • assertSame (object expected, object current): This only supports objects and uses the == operator to check object references. If two different objects are passed, an AssertionError will be thrown.
  • assertNotSame: This is the exact opposite of assertSame. If the two-argument references are the same, it will fail.

We will use the assert methods in the test as follows:

1. Create a AssertTest test class under com.packtpub.junit.recap. Add the following lines to the class:

package com.packtpub.junit.recap;
 
import org.junit.Assert;
import org.junit.Test;
 
public class AssertTest {
 
  @Test
  public void assertTrueAndFalseTest() throws Exception {
    Assert.assertTrue(true);
    Assert.assertFalse(false);
  }
  
  @Test
  public void assertNullAndNotNullTest() throws Exception {
    Object myObject = null;
    Assert.assertNull(myObject);
    
    myObject = new String(“Some value”);
    Assert.assertNotNull(myObject);
  }
}

In the above code, assertTrueAndFalseTest sends true to assertTrue and false to assertFalse. Therefore, the test should not fail.
assertNullAndNotNullTest passes null to assertNull and a non-null string to assertNotNull. Therefore, this test should not fail.
Run the test. They should be green.

2. We will examine assertEquals and add the following test and static import the assertEquals method:

import static org.junit.Assert.assertEquals;
 
  @Test
  public void assertEqualsTest() throws Exception {
    Integer i = new Integer(“5”);
    Integer j = new Integer(“5”);;
    assertEquals(i,j);
  }

The previous code defines two integer objects i and j, which are initialized to 5. If you pass them to assertEquals now, the test will pass because the assertEquals method calls i.equals (j) instead of i == j. Therefore, only the values ​​are compared, not the references.
The assertEquals method works for all primitive types and objects. To validate the Double value, use the loadedassertEquals (actual, Expected, Delta) method, or use BigDecimal instead of Double.

4. Add a test to verify the assertNotSame behavior and static import the assertNotSame method:

import static org.junit.Assert.assertNotSame;
  @Test
  public void assertNotSameTest() throws Exception {
    Integer i = new Integer(“5”);
    Integer j = new Integer(“5”);;
    assertNotSame(i , j);
  }

The assertNotSame method fails only if the expected object and the actual object refer to the same location. Here, the values ​​of i and j are the same, but the memory references are different.

4. Add a test to verify the assertSame behavior and static import the assertSame method:

import static org.junit.Assert.assertSame;
  @Test
  public void assertSameTest() throws Exception {
    Integer i = new Integer(“5”);
    Integer j = i;
    assertSame(i,j);
  }

The assertSame method is passed only if the expected object and the actual object refer to the same memory location. Where i and j have the same value and refer to the same location.

Working with exception handling

Exception handling is important for testing error conditions. For example, the API requires three objects. If the argument is null, the API should throw an exception. This is easy to test. If the API does not throw an exception, the test will fail. The @Test annotation takes the expected=<<Exception class name>>.class argument. If the expected exception class does not match the exception thrown by the code, the test will fail. Consider the following code:

  @Test(expected=RuntimeException.class)
  public void exception() {
    throw new RuntimeException();
  }

Ignoring a test

Instead of annotating the test, you can use @Ignore to annotate the test method and ignore it. Commenting out tests and code has bad results, as it only increases the code size and reduces readability. When I comment out a test, the test report does not show anything about the commented-out test. However, ignoring the tests indicates that some tests are being ignored and the test report needs correction. This is a way to track ignored tests. Use @Ignore (“Reason: Why do you want to ignore it?”). The correct explanation explains the intent behind ignoring the test. The following is an example where the check method is ignored because the vacation calculation does not work.

@Test
@Ignore(“John’s holiday stuff failing”)
public void when_today_is_holiday_then_stop_alarm() {
}

You can place the @Ignore annotation on a test class, effectively ignoring all the contained tests.

Executing tests in order

For example, if you want to create a slow test that inserts a row into the database, update the row first and then delete it. Here, the delete or update function cannot be executed unless the insert function is executed.
JUnit 4.11 provides the @FixMethodOrder annotation to specify the execution order. Requires enums MethodSorters.
To change the execution order, annotate the test class with @FixMethodOrder and specify one of the following available EnumMethodSortersconstant:

  • MethodSorters.JVM: This leaves the test methods in the order returned by the JVM. This order may vary from run to run.
  • MethodSorters.NAME_ASCENDING: This sorts the test methods by lexicographic order by method name.
  • MethodSorters.DEFAULT: This is the default value and does not guarantee the execution order.

Let’s create some tests to verify this behavior.
Add a TestExecutionOrder test and create the test as shown in the code snippet below:

public class TestExecutionOrder {
  @Test   public void edit() throws Exception {
    System.out.println(“edit executed”);
  }
  @Test   public void create() throws Exception {
    System.out.println(“create executed”);
  }
  @Test   public void remove() throws Exception {
    System.out.println(“remove executed”);
  }  
}

Run the tests. The execution order may vary, but if we annotate the class with @FixMethodOrder(MethodSorters.NAME_ASCENDING), the tests will be executed in the ascending order as follows:

@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class TestExecutionOrder { … }

The following Eclipse screenshot displays the test execution in the ascending order:

JUnit TUTORIAL

Learning assumptions

Like Assert, Assume provides many static methods such as assumeTrue (Condition), assumeFalse (Condition), assumeNotNull (Condition), and assumeThat (Condition). Before running the test, you can use the adoptXXX method to validate your assumptions. If the assumption fails, the acceptXXX method throws an AssumptionViolatedException and the JUnit runner ignores the failed assumption test.
Create an acceptance test class. The body of the class is:

public class Assumption {
   
  boolean isSonarRunning = false;
  @Test
  public void very_critical_test() throws Exception {
    isSonarRunning = true;
    Assume.assumeFalse(isSonarRunning);
    assertTrue(true);
  }
  
}

Here, for simplicity, we added a isSonarRunning variable to replicate a SONAR server facade. In the actual code, we can call an API to get the value. We will set the variable to false. Then, in the test, we will reset the value to true. This means SONAR is running. So, our assumption that SONAR is not running is false; hence, the test will be ignored.

The following screenshot shows that the test is ignored. We didn’t annotate the test using @Ignore:

JUnit TUTORIAL

Exploring the test suite

To run multiple test cases, JUnit 4 provides Suite.class and @ Suite.SuiteClasses annotations. This annotation takes an array of test classes (comma separated). Create a TestSuite class and annotate the class with @ RunWith (Suite.class). This annotation causes Eclipse to use the suite runner. Then annotate the class with @ Suite.SuiteClasses ({AssertTest.class, TestExecutionOrder.class, Assumption.class}) and pass the comma-separated test class name. The code snippet is:

import org.junit.runner.RunWith;
import org.junit.runners.Suite;
 
@RunWith(Suite.class)
@Suite.SuiteClasses({ AssertTest.class, TestExecutionOrder.class,Assumption.class })
public class TestSuite {
 
}

During execution, the suite runs all tests. Following is a screenshot of running the suite. Make sure that 7 tests are running from 3 test devices (AssertTest, TestExecutionOrder, and Assumption).

Working with timeouts

JUnit testing is automated so you can get quick feedback after changing your code. If the test runs too long, it violates the quick feedback principle. JUnit provides a timeout value (in milliseconds) for the @Test annotation to ensure that the test fails if it runs longer than the specified value. The following is an example of a timeout.

  @Test(timeout=10)
  public void forEver() throws Exception {
    Thread.sleep(100000);
  }

Here, the test will automatically fail after 10 milliseconds.