JavaData & JavaExploring Java Unit Testing with the JUnit Test Framework

Exploring Java Unit Testing with the JUnit Test Framework

Developer.com content and product recommendations are editorially independent. We may make money when you click on links to our partners. Learn More.

JUnit is a third-party, open source unit testing framework. The project was started by Kent Beck and Erich Gamma in late 1995. It quickly garnered interest in the community of developers who particularly deal in test-driven development. JUnit was initially introduced to Smalltalk, but later was ported to Java, which quickly picked this up as a de-facto standard of unit testing. The popularity of JUnit grew to an extent that, to cater to the needs of many other contemporary languages such as C#, Perl, Python, PHP, Ruby, Visual Basic, C++, and so forth, a generic xUnit framework was developed where the letter ‘x’ is replaced by the first letter of the language, such as JUnit for Java, RUnit for Ruby, and so on. This article provides an overview of this framework as used by the de-facto standard of Java unit testing.

Testing Overview

Testing is an important phase in the life cycle of an application development. The main purpose of testing is to evaluate a program on the basis of required specifications. The target is to create certain test cases that surface errors, gaps, any discrepancies or unexpected outcome, as much as possible. This simple concept has some elaborate processeses associated with it. But, to put it briefly, it is done at three levels. When the testing is done at the very granular or individual component level, it is called Unit Testing; when they are combined to check the interfaces between components against a software design, it is called Integration Testing; and finally, when the complete system is integrated and testing is done to verify that the system as a whole meet the requirement specified, it is called System Testing.

Unit Testing

In a nutshell, performing a unit test is a way to examine the behaviour of a distinct unit of code. In Java, a unit of code may mean a method or a class or even a module, according to the context. If it is a method, for example, the focus of the test is on evaluating the right object reference allowed to invoke the method, type of parameters and acceptable values, primitive value ranges, return type and value, and so on. The idea is to grill the method so that it can be made robust enough to gracefully handle its problem and throw those which are beyond its scope apart from fulfilling its contract.

Therefore, unit testing forms the basic building block of any program evaluation. In fact, every programmer performs some sort of unit testing as one writes code to check the outcome of the code with some dummy data/cases. Unit testing is thus a formal status given to that isolated collection of tests. It is extremely important that a code goes through the rigor of various phases of testing. The unit testing, apart from its importance, it is also very commonplace. People such as Kent Beck and Erich Gamma thought of creating a framework for it so that programmers get a structured environment and can automate many of these tasks. After all, this is what a framework is for. Typically, it provides a coherent program structure that is reusable and shareable across applications. A programmer can incorporate them into an existing application and extend them according to its specific need.

A Quick Example

A simple unit testing code to examine the single method in Temperature class without using JUnit framework is as follows:

package org.mano.unittest.examples;
public class Circle {
   double area(double radius) {
      returnMath.PI* radius * radius;
   }
}

Now, let’s write the code to unit test the area method.

package org.mano.unittest.examples;

public class CircleTest {
   public int errCounter= 0;
   public void testCircleArea() {
      Circle circle = new Circle();
      double area = circle.area(12);
      if (area < 452 && area > 453) {
         throw new IllegalStateException("Wrong calculation!: "
            + area);
      }
   }

   public static void main(String[] args) {
      TestCircle test = new TestCircle();
      try {
         test.testCircleArea();
      } catch (Throwable e) {
         test.errCounter++;
         e.printStackTrace();
      }
      if (test.errCounter> 0) {
         throw new IllegalStateException("There were "
            + test.errCounter+ " error(s)");
      }
   }
}

This is a rudimentary example, but gives you an idea about how unit testing may be done without using any framework.

JUnit Testing Framework

Using JUnit framework for unit testing has several advantages. It provides numerous annotations that make it easy to write and run test codes in Java:

  • Primarily, it separates the concern of unit testing from the actual project code by enabling one to create a test class instance and class loaders for each unit test. These “immune” the existing code from unnecessary side effects of testing.
  • The annotations provided by JUnit—such as @Before, @After, @BeforeClass, @AfterClass—have methods for both resource initialization and resource reclamation.
  • There is a wide variety of assert methods to verify the result of a test.
  • Over the years, JUnit became so popular that numerous Java tools, such as Ant and Maven; and popular IDEs, such as Eclipse, NetBeans, IntelliJ IDEA, and the like, comes with inbuilt integration of JUnit.

To use the JUnit Test Framework in a Java project, one must add a JUnit JAR file into the project class path. This is explicitly required if the IDE is not integrated with the JUnit library. The process is simple. Download the JAR file and add it to the project class path.

Here are some important links to JUnit framework.

Unlike JUnit 4 and its predecessors, JUnit 5 brought some significant changes. Apart from many new features added&mdahs;like lambda support, new annotations, and test method parameter injection—the core architecture got some significant modification. JUnit 5 is now a composite architecture of three different modules: JUnit Jupiter, JUnit Vintage, and JUnit Platform. The test case developers, however, do not need to bother about the intricacies of changes. The changes primarily mean better tool support, consistency, and cleaner APIs. Above all, it is outright backward compatible with JUnit 4. So, no worries there either. Refer to the JUnit 5 user guide for more details.

A Quick Example

Here is a very simple example to get a glimpse into how unit testing may be done with the JUnit framework. We use the Employee class for the unit test and create a test class to give an idea of its workings. The example is rudimentary to the extent of writing a ‘Hello World’ program. Real-world test cases, or even a decent example of unit test, requires a good amount of code. Maybe we’ll try that in some other article.

package org.mano.unittest.examples;
public class Employee {
   private final String name;
   private final double basicPay;
   public Employee(String name, double basicPay) {
      this.name=name;
      this.basicPay=basicPay;
   }
   public String getName() {
      return name;
   }
   public double getBasicPay() {
      return basicPay;
   }
}

package org.mano.unittest.examples;
import org.junit.Test;
import static org.junit.Assert.*;
public class EmployeeTest {
   @Test
   public void constructorInitTest(){
      Employee emp=new Employee("Odin", 2300);
      assertEquals("Odin", emp.getName());
      assertEquals(2300, emp.getBasicPay(), 0.001);
   }
}

package org.mano.unittest.examples;
public class EmployeeTestMain {
   public static void main(String[] args){
      EmployeeTest et=new EmployeeTest();
      et.constructorInitTest();
   }
}

Observe that the Employee class is immutable with only two fields set by the constructor. Because only the contructor method is worth testing, we’ll test that only.

The test class is named EmployeeTest as per convention. The annotation @Test enables JUnit to designate a method as a test method. There are a variety of assert methods in the Assert class. Here, we have used only assertEquals.

There are many ways to run a test written in JUnit. Typically, after the test cases run, it prints a summary. It, however, might vary depending on how the test is run. It may run through IDEs like Eclipse or IntelliJ, or tools like Maven, Gradle, and so forth. Sometimes, the only information received after the test is that it has either failed or passed.

Conclusion

There are several other frameworks for unit testing. JUnit is a popular unit testing framework among the Java Community. Testing as a system engineering phase has a lot more process involved with it. Unit testing is just a part of it and, interestingly, a lot of play test that are done by the developer can be termed as unit testing. JUnit, as a test framework, adds value to it. The annotations and the APIs provided by JUnit automate many a task and make life a lot easier for the unit test developers.

Get the Free Newsletter!

Subscribe to Developer Insider for top news, trends & analysis

Latest Posts

Related Stories