Introduction to Unit Testing with JUnit and Mockito

Overview

1. Introduction

In this article, we will visit the JUnit and Mockito testing frameworks and learn how to take the first steps with them.

2. The JUnit and Mockito Testing Frameworks

JUnit is a testing framework to validate our code against test scenarios that we create. Mockito is an extension of JUnit that helps to create mock classes. These two frameworks make it easier to assert equality and inequalities, how many times we call a method, mock external class behaviors, and more.

JUnit and Mockito are fully compatible with most Java-related frameworks like Spring, Micronaut, Vert.x, etc., and build systems like Maven or Gradle.

3. How to Configure JUnit and Mockito

We can configure JUnit and Mockito using either Maven or Gradle, depending on which one your project uses. In both cases, we can get the latest version of JUnit from the JUnit Official User Guide and Mockito from the Mockito Git Repository.

In this tutorial, we'll use Unit 5 and Mockito 4 together with the Maven build tool.

3.1. Importing JUnit and Mockito Using Maven

Let's create the initial configurations for JUnit and Mockito. To do so, initialize a Spring application using the Spring Initialzr website and import it to IntelliJ IDEA. After creating the Spring application, we can add the needed dependencies in our pom.xml file. The code below shows part of the content of my pom.xml with Mockito 4.8.1 and JUnit 5.9.1:

 1    <dependencyManagement>
 2        <dependencies>
 3            <dependency>
 4              <groupId>org.junit</groupId>
 5              <artifactId>junit-bom</artifactId>
 6              <version>5.9.1</version>
 7              <type>pom</type>
 8              <scope>import</scope>
 9            </dependency>
10        </dependencies>
11    </dependencyManagement>
12
13    <dependencies>
14        <dependency>
15          <groupId>org.junit.jupiter</groupId>
16          <artifactId>junit-jupiter</artifactId>
17          <scope>test</scope>
18        </dependency>
19
20        <dependency>
21          <groupId>org.mockito</groupId>
22          <artifactId>mockito-core</artifactId>
23          <version>4.8.1</version>
24          <scope>test</scope>
25        </dependency>
26    </dependencies>
27</project>

4. First Steps with JUnit

Let's try an example of a simple unit test with JUnit that adds two numbers and assert if the result is equal to an expected number:

 1public class MyFirstUnitTest {
 2
 3    @Test
 4    public void given2And3_whenAdded_thenReturn5(){
 5        //given
 6        int two = 2;
 7        int three = 3;
 8
 9        //when
10        int result = two + three;
11
12        //then
13        assertEquals(5, result);
14    }
15}

Yet simple, there are valuable outcomes from the code above:

  1. The test name is written in a Behavior-Driven Development format, using the given/when/then format. That format defines the inputs (given), the action (when), and the expected result (then) if a specific format, which helps others to understand the test.
  2. Even though, in this case, we have just two possible numbers to add, it is a good practice always to keep them in variables. That is especially useful for creating Parameterized Tests.

5. A Bit About Mockito

Mockito is useful when we want to mock results from a specific method call from a class. Imagine that you want to test a class that depends on a second class. The expected behavior of the second class should not be part of the first class unit test. Each class should have its specific unit test. We can mock a method from the second class to avoid that issue.

Mocking refers to given a method and some arguments, always return a specific result from that method. Let's try one example of mocking with the unit test described earlier.

 1    ArrayList<Integer> list = mock(ArrayList.class);
 2
 3    @Test
 4    public void given2And3_andListReturns6_whenAdded_thenReturn11(){
 5
 6        int two = 2;
 7        int three = 3;
 8
 9        when(list.get(0)).thenReturn(6);
10
11        int result = two + three + list.get(0);
12
13        assertEquals(11, result);
14    }

The when method makes any call to list.get(0) inside that unit test to return 6. Using mocks, we can keep the tests isolated from external dependencies behavior.

6. Conclusion

In this article, we've seen how to configure JUnit and Mockito in a Spring Boot Application and how to take the first steps with them.