Unit Testing with JUnit

JUnit is a java unit testing framework which was developed back in 1995. Ever since then its popularity has been growing and is now a major unit testing framework used to test Java applications.

Let's start by creating a simple calculator, that performs some basic arithmetic operation.

Below is our calculator class:

public class Calculator {
    
    public int add(int a, int b){
        return a + b;
    }
    
    public int subtract(int a, int b){
        return a - b;
    }
    
    public int multiply(int a, int b){
        return a * b;
    }
    
    public int divide(int a, int b){
        return a / b;
    }
}

Now that we have created our calculator class we need a way to test it, we will write a JUnit Test to test our calculator. Below is our test class:

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


public class CalculatorTest {
    
    private static Calculator calc;
    private int result;
    
    @BeforeClass
    public static void switchOn(){
        System.out.println("Switching On Calculator");
        System.out.println("-----------------------");
        calc = new Calculator();
    }
    
    @AfterClass
    public static void switchOff(){
        System.out.println("Switching Off Calculator");
        calc = null;
    }
    
    @Before
    public void setup(){
        System.out.println("Press CE");
        result = 0;
    }
    
    @After
    public void cleanUp(){
        System.out.println("Press C");
        System.out.println("-----------------------");
    }
    
    @Test
    public void testAdd(){
         System.out.println("Perform Addition");
         result = calc.add(10, 12);
         assertEquals(22, result, 0); 
    }
    
    @Test
    public void testSubtract(){
        System.out.println("Perform Subtraction");
        result = calc.subtract(20, 10);
        assertEquals(10, result, 0);
    }
    
    @Test
    public void testMultiply(){
        System.out.println("Perform Multiplication");
        result = calc.multiply(5, 10);
        assertEquals(50, result, 0);
    }

    @Test
    public void testDivide(){
        System.out.println("Perform Division");
        result = calc.divide(20, 4);
        assertEquals(10, result, 0);
    }

    @Ignore
    @Test
    public void ignoreMe(){
        System.out.println("Ignore Method");
    }
}

Understanding the Test Class

We will start by creating a class named 'CalculatorTest'. This class is a general plain java class, only restriction we have here is that the class must be public. We have a couple of variable declarations and few methods with some annotations.

Below table shows the purpose of each of these annotations.

Annotation Description
@Test This is used to indicate that the method is a test method.
@Ignore This is used to indicate that the test method must be ignored and should not be executed.
@Before The method annotated with @Before is executed before execution of each test method. It can be used to initialize classes, read inputs etc. The method must be declared as public.
@After The method annotated with @After is executed after execution of each test method. It is used for cleanup the temporary data created by the test method in order to save memory. The method must be declared as public.
@BeforeClass Executed only once before starting the tests. It is used to perform time sensitive operations like I/O operations, database hits etc. The method must be declared as public static.
@AfterClass Executed only once after the tests are executed. It is used to perform cleanup activities and release resources acquired by the test class like close database connection, close files etc. The method must be declared as public static.

In each of these test methods, we call a method of the calculator class that we want to test. We use the assertEquals() method to validate the result returned from the method under test. We validate this result against the expected result. Notice the testDivide() method where we have purposely set the expected result to '10' so that the assertion fails. This is done to test a failure scenario.

Note: assertEquals() is a method from org.junit.Assert class, which we have imported to the CalculatorTest class as a static import. This method takes 2 parameters, the expected result and the actual result. If actual result != expected result, then an AssertionError is thrown.


Executing the Test Class

Considering that we are using eclipse, simply right click on the CalculatorTest class, select 'Run As' --> 'JUnit test'

It would print the following output in the console:

Switching On Calculator
-----------------------
Press CE
Perform Addition
Press C
-----------------------
Press CE
Perform Subtraction
Press C
-----------------------
Press CE
Perform Division
Press C
-----------------------
Press CE
Perform Multiplication
Press C
-----------------------
Switching Off Calculator

As we can see the following in the console output:

  • The switchOn() and switchOff() methods are only called once, before and after the execution of the test respectively.
  • The tests get executed after the switchOn() method is executed.
  • The setUp() and cleanUp() methods are executed before and after the execution of each method.
  • The ignoreMe() method is ignored and not included in the test run.

Below image shows the JUnit report generated for Calculator test class.

We can notice here that the except the testDivide() method other methods have passed the unit test. Also the ignoreMe() method has been ignored.

RELATED ARTICLES

Grouping Of Tests using JUnit Categories

JUnit provides the developers with an opportunity to group multiple tests into a single category, thus creating the possibility to include or exclude the category during execution of the test case.

View Article

Testing Exception and Timeout with JUnit

Apart from testing positive scenarios, JUnit can also be used to test negative scenarios. It can be used to test scenarios where an exception is expected or a timeout is to be checked.

View Article

Testing with Multiple Inputs using Parameterized Runner

JUnit Parameterized Test Runners provides the abiltiy to run the same test over and over again using different set of inputs.

View Article

Introducing JUnit Rule

Junit Rules allows developers to add additional functionalities that can applied to all test methods in a test class. It is similar to the concept of custom test runners but with reduced restrictions.

View Article

Understanding JUnit Test Suite

A JUnit Test Suite allows developers to bundle multiple test classes together into a single unit (called as test suite) and run them all together at once.

View Article