opencodez

Unit Testing of Java Application using JUnit with Example – Simple Detailed Guide

Unit testing is the process of testing individual units or components of the software. With unit testing, the smallest part of the software is tested like a class, method, or even a line of code.

In this post, we will learn the Unit Testing of Java Application using Junit. We will learn, how to download, integrate, and run JUnit test cases in Java projects.

Unit Testing of Java Application using Junit:

The best time to write the unit test code is during the development time. The developer who wrote the code will like to know how it works and what are the scenarios that need to be tested.

JUnit is one of the most popular unit testing Java framework. It is easy to understand, easy to integrate and the best thing is that it is open-sourced. JUnit uses annotations and assertions for writing test cases. It provides a test-runner to identify and run all the test methods in a project.

JUnit Installation:

JUnit is available to download as a Jar file and also you can add it as a dependency for any maven or Gradle project.

  1. Jar file: Check this page to download the latest jar files
  2. Maven: You can add it on a Maven project by using the following dependency:
    xdependencyx 
               xgroupIdxjunitx/groupIdx 
               xartifactIdxjunitx/artifactIdx 
               xversionx4.12x/versionx 
               xscopextestx/scopex 
    x/dependencyx
  3. Gradle:
    For using JUnit with Gradle projects, add the below dependency in your build.gradle file
    apply plugin: 'java'
    
    dependencies {
               testCompile 'junit:junit:4.12'
    }

The latest version is x4.12x at the time of writing this blog post. You can check this page to download the latest build.

Note that two versions of JUnit are available: JUnit4 and JUnit5. In this post, we are covering the use cases of xJUnit4x.

I am assuming that you are either familiar with Gradle or Maven Java projects. The standard convention for Maven or Gradle build tools is to use a separate folder for writing all tests.

Normally, the xsrc/main/javax folder is used for the source Java files and xsrc/test/javax folder is used for the Unit Test files. This process makes it easier to organize all source code and test code separately.

How to run a Unit test :

You can run a unit test directly using a command line or with an IDE.

Writing your first test:

 For writing our unit tests, we need to create one test class in the xsrc/test/javax folder. Create one basic Java project on Eclipse or IntelliJ-Idea and create one class TemperatureCalculator.javax inside the xsrc/main/javax folder :

public class TemperatureCalculator {

    public float toFahrenheit(float degree) {
        return (degree * 9 / 5) + 32;
    }

    public float toDegree(float fahrenheit) {
        return (fahrenheit - 32) * (float) (5.0 / 9.0);
    }
}

As you can see that this class can be used to convert a temperature reading in Fahrenheit (°F) to Celsius (°C) and vice versa. Now, we will write one new test-class to test these methods. Create one class xTemperatureCalculatorTest.javax inside xsrc/main/testx folder :

import static org.junit.Assert.assertEquals;
import org.junit.Test;

public class TemperatureCalculatorTest {
    @Test
    public void testToDegree(){
        TemperatureCalculator calculator = new TemperatureCalculator();
        assertEquals(36.666668f,calculator.toDegree(98),0);
    }

    @Test
    public void testToFahrenheit(){
        TemperatureCalculator calculator = new TemperatureCalculator();
        assertEquals("Test failed for Degree to Fahrenheit",100f,calculator.toFahrenheit(100),0);
    }
}
Here,

We have two Test methods here: xtestToDegreex and xtestToFahrenheitx. The first one will test the xtoDegreex method and the second one will test the xtoFahrenheitx method of the xTemperatureCalculatorx class. x@Testx annotation is used to define a test method.

Inside each of these test methods, we are verifying one condition using the xassertEqualsx method. Note that the arguments are different in both cases for xassertEqualsx. It is an overloading method and a lot of other versions of this method are also available. We will discuss that later in this post. For using xassertEqualsx method, we need to import the xorg.junit.Assert.assertEqualsx package.

Inside xtestToDegreex method, xassertEqualsx is checking if the value of xcalculator.toDegree(98)x is equal to x36.666668fx or not. If the values are not equal, it will show one error to the user. Similarly, inside xtestToFahrenheitx method, it is checking if the value of xcalculator.toFahrenheit(100)x is equal to x100fx or not. If it is not true, it will throw one error with a message xTest failed for Degree to Fahrenheitx to the user.

If you run these unit tests, the first test method i.e. xtestToDegreex will run without any issue. But the second method will throw one exception like below :

java.lang.AssertionError: Test failed for Degree to Fahrenheit
Expected: 100.0
Actual :212.0

So, the actual value or the value of xcalculator.toFahrenheit(100)x is x212.0x, but we are expecting x100.0x in the statement, which is not equal. It prints the same error message that we have provided.

Test Execution Order:

 By default, JUnit executes all tests indeterministic but not predictable order i.e. a unit test should not depend on the output of any other test. But JUnit also provides us with three options to sort the tests defined in a class. You can annotate your test class with any of the below annotations :

  1. @FixMethodOrder(MethodSorters.NAME_ASCENDING): It will run the tests in lexicographic order
  2. @FixMethodOrder(MethodSorters.JVM): It will use the natural JVM ordering for running the tests. Note that it may vary for different executions.
  3. @FixMethodOrder(MethodSorters.DEFAULT): This is the default option.

Other Test Method Annotations:

 We have seen in the above example that annotation is required to mark a method as a test method in JUnit. Following are a few important annotations we can use in JUnit :

 @Test : You can use this annotation to identify a test method. The method should be xpublic voidx.

 @Test(timeout): The test method will fail if the execution takes more than xtimeoutx milliseconds.

 @Before : This annotation is used to run a method before each test. It is used for common tasks like object creation, reading user input etc.

 @After : It is used to run a method after each test. If we create anything in the xBeforex method, xAfterx method can be used to release them.

 @BeforeClass : It executes only one time before all test methods. It can be used to set up common time taking operations like connecting to a database.

 @AfterClass : It executes after all test methods. If we set up anything in xBeforeClassx, xAfterClassx can be used to release them.

 @Ignore : You can use it to disable a test or a group of tests temporarily.

Verify conditions using Assert Statements:

 Assert statements are static methods to check certain conditions in JUnit tests. These methods are used to compare one user-provided value with the actual value returned by the test method. If the comparison fails, it throws one xAssertionExceptionx. I am listing down a few of these Assert methods. You can check the official documentation to check the other methods as well.

 assertArrayEquals(message, expected, actual) :

message : String variable to print if it fails. This is an optional value.

expected : expected array

actual : actual array returned by the test method

The array can be of type Object[], boolean[], byte[], char[], int[], long[] or short[]

 assertEquals(message , expected, actual) :

message: Optional String message to print if it fails.

expected: expected value

actual: actual value returned by the test method

The values can be of double, float, long or object type.

assertNotEquals(message , expected, actual) :

Opposite of xassertEqualsx statement. The xexpectedx and xactualx can be of double, float, long or object type.

assertNull(String message, Object object): Assert that object is null. xmessagex is optional.

assertNotNull(String message, Object object) : Assert that the xobjectx is not null. xmessagex is optional.

assertSame(String message, Object expected, Object actual): Assert that xexpectedx and xactualx objects are referring to the same object. xmessagex is optional.

assertNotSame(String message, Object uexpected, Object actual): Assert that xuexpectedx and xactualx objects are not referring to the same object. xmessagex is optional.

assertNull(String message, Object object) : Assert that xobjectx is null. xmessagex is optional.

assertNotNull(String message, Object object) : Assert that xobjectx is not null. xmessagex is optional.

assertTrue(String message, boolean condition) : Assert that xconditionx is true. xmessagex is optional.

fail(message) : Fail a given test. The xmessagex is optional.

Conclusion

Testing improves the quality of the code and it makes the development process more Agile. Just imagine the effort requires to change the design of software with hundreds of class files. If we have unit tests written for all these classes, we can confidently do the refactoring.

It also helps us to find out the bugs easily during development time. As a software developer, we should always take testing seriously.