Simple guide for Unit Testing of Java Application using JUnit with Example

Unit testing is the process of testing individual unit or component of a software. With unit testing, the smallest part of the software is tested like a class, method or even a line of code. 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 conditions 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. In this post, we will learn how to download, integrate and run JUnit test cases in Java projects.

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:
  3. Gradle:
    For using JUnit with Gradle projects, add the below dependency in your build.gradle file

The latest version is ‘4.12’ 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 “JUnit4”.

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 ‘src/main/java’ folder is used for the source Java files and ‘src/test/java’ 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.

  • Using command line: Use the below command to run a test case using the command line :
    java -cp /path/to/junit.jar org.junit.runner.JUnitCore <test-class>
  • Using Eclipse: Go to the source code explorer, right click on the test class. Click on Run As → JUnit Test
  • Using IntelliJ-Idea: Right click on the test class. Click on “Run <Test-Class>”

Writing your first test:

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

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 ‘TemperatureCalculatorTest.java’ inside ‘src/main/test’ folder :

Here,

We have two Test methods here: ‘testToDegree’ and ‘testToFahrenheit’. The first one will test the ‘toDegree’ method and the second one will test the ‘toFahrenheit’ method of the ‘TemperatureCalculator’ class. ‘@Test’ annotation is used to define a test method.

Inside each of these test methods, we are verifying one condition using the ‘assertEquals’ method. Note that the arguments are different in both cases for ‘assertEquals’. 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 ‘assertEquals’ method, we need to import the ‘org.junit.Assert.assertEquals’ package.

Inside ‘testToDegree’ method, ‘assertEquals’ is checking if the value of ‘calculator.toDegree(98)’ is equal to ‘36.666668f’ or not. If the values are not equal, it will show one error to the user. Similarly, inside ‘testToFahrenheit’ method, it is checking if the value of ‘calculator.toFahrenheit(100)’ is equal to ‘100f’ or not. If it is not true, it will throw one error with a message “Test failed for Degree to Fahrenheit” to the user.

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

So, the actual value or the value of ‘calculator.toFahrenheit(100)’ is ‘212.0’, but we are expecting ‘100.0’ 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 ‘public void’.

 @Test(timeout): The test method will fail if the execution takes more than ‘timeout’ 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 ‘Before’ method, ‘After’ 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 ‘BeforeClass’, ‘AfterClass’ 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 ‘AssertionException’. 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 ‘assertEquals’ statement. The ‘expected’ and ‘actual’ can be of double, float, long or object type.

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

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

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

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

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

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

assertTrue(String message, boolean condition) : Assert that ‘condition’ is true. ‘message’ is optional.

fail(message) : Fail a given test. The ‘message’ 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.

Add a Comment

Your email address will not be published. Required fields are marked *