Unit Testing in Java

Mercy Jemosop
6 min readJul 19, 2022

--

Mocking your application in Java

Introduction

Unit Testing is a methodology of testing source code to check the independent modules of a software app during the development phase. It is done by developers during the coding phase before integration testing. It can be a procedure or a function.

Integration Testing is where the different units, modules or components of a software application are tested as a combined entity. It involves integrating the various modules of an application and then testing their behavior as a combined.

An in-memory database stores data in the system memory rather than on a disk.because accessing data on a drive takes longer than memory.
When we don’t require the data to be persistent, we use the in-memory database.An embedded database is the in-memory database.By design, in-memory databases are unstable(volatile), and when we restart the application, all stored data is lost. Example H2, HSQLDB (HyperSQL Database), and Apache Derby.

In this tutorial, we are going to go over unit testing in java. Unit testing is a good practice which every developer should adapt to make sure the code meets quality standard before being deployed.We use in-memory during unit testing to enable us to quickly generate a clean data base for unit tests to run against and quickly remove/delete the database after the test cycle phase has been completed.Physical database creation and deletion would take a lot of time, slowing down your local build.

N.B When you want to test your code against your target DBMS (postgreSQL) we use integration testing.

JUnit5 guide

Let’s get started

Create a new Spring-boot project using start.spring.io. for our application.

If you new to spring-boot here is a tutorial for creating a new spring-boot project.

Add the dependencies below to your project

Requirements/ dependencies

  1. H2 is an embedded, open source and in-memory relational database management system written in java. It’s generally used for unit testing and stores data in memory. H2 is a client/server application.
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>test</scope>
</dependency>

2. spring-boot-starter-test is the primary element which contains the majority of elements required for unit testing.

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>

3.spring-boot-starter-validation is a starter for using Java Bean Validation with Hibernate Validator

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>

4.Spring data Jpa, it improves the implementation of the data access layers by reducing effort to the amount that is needed.

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>

5. PostgreSQL

<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<scope>runtime</scope>
</dependency>

6.Starter for building web, including Restful application using spring MVC. It uses tomcat as the default embedded container.

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>

Check here if you are missing any dependancy.

github url to the pom.xml file with all dependencies.

Application.Properties file

The next step is to add our in- memory and postgresql configurations to our application. We will edit the application.properties file in the resource folder.

For the DBMS configuration, create a database and replace the database name, username and password

server.port=8080
server.error.include-message=always
server.error.include-binding-errors=always

spring.datasource.url=jdbc:postgresql://localhost:5432/yourDBName
spring.datasource.username=yourDBusername
spring.datasource.password=yourDBpassword
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect
spring.jpa.properties.hibernate.format_sql=true

github link to application.properties file

During unit testing, we will be using the in memory for test cases not the main database. To configure h2 database. Navigate to the test folder under src

unittesting/src/test/

  1. Create a new resource folder.
  2. inside the resource folder create application.properties file for the in-memory configuration.

Add this configuration to your application.properties under test.

spring.datasource.url=jdbc:h2://mem:db;DB_CLOSE_DELAY=-1
spring.datasource.username=sa
spring.datasource.password=sa
spring.datasource.driver-class-name=org.h2.Driver
spring.jpa.hibernate.ddl-auto=create-drop
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect
spring.jpa.properties.hibernate.format_sql=true

github link to application.properties under test

run you application to ensure all goes well.

N.B make your you create a DB / add the right credentials to the application.properties under main. /src /main/resource/application.properties

Some Simple unit test for performing calculations.

unit test for the Calculation class

With that simple example let’s dive in to some CRUD examples. Before getting stated, create an entity class and a repository for our crude Application. The source of most of the code is Amigoscode, you can check for the tutorial on youtube.

  1. Create an entity Class. Add lombok dependency to be able to use @Getter and @Setter annotations

2. Create a repository.

3.Create a simple method to fetch all users. You can create a service class (UserServiceImpl)without implementing the UserService class and remove the @override annotation

Unit test for fetching users

To create a unit test for this query we have created.

  • open your service class.
  • Then CTL+SHIFT+T or right click you service class, click generate,click test. You will get pop up below

Select the method you need only for now and leave other fields.

If you navigate to your test directory/package, you will see the test class.

@ExtendWith()- this annotation is used to load a Junit extension which allows third party vendor like mockito to hook into life cycle of running test cases and add additional functionality. It Initializes mocks annotated with @Mock, so that explicit usage of MockitoAnnotations#initMocks(Object) is not necessary. Mocks are initialized before each test method.

@ExtendWith(MockitoExtension.class) this is used when you don’t want to involve spring since it does not load unnecessary spring features. If you need some spring features use this @ExtendWith(SpringExtension.class).

@mock- annotation is used to create mocks that are needed to support the testing of the classes to be tested.

Mocking in unit testing is used when the unit being tested has external dependencies. It is useful when you want to test interaction between class under test and a particular interface.

@BeforeEach annotation is used to signal that the annotated method should be executed before each invocation of @Test,@RepeatedTest,@ParameterizedTest or @TestFactory method in the current class. So in our case the setUp() method is executed first then the getUsers() method and other methods with the @Test annotation.

To verify that specific behavior occurred, mockito verify methods are utilized. To ensure that specified methods are called, we can add Mockito verify methods at the conclusion of the testing method code.

To test your service class test coverage right click on your test class and run with coverage or click the test Icon and select run with coverage

This was an easy example. Let’s add another method to add a User. Update the implementation class with this method.

The addUser method above can be separated into two test cases

  • To check if email exist and the userRepository.save method is not invoke but the email taken message is thrown.
  • When email does not exist and the new user is saved.

Mockito ArgumentCaptor allows us to capture an argument passed to a method in-order to inspect it.Useful when we can’t access the argument outside of the method we’d like to test.

We can then get the captured value and store it as a new Users object. Read more here.

Delete a user method , update the service implementation class with the method below. Similar with the add user, we will separate when success and when error is thrown in the test cases.

unit test for deleting a user.

Continuation of unit testing

GitHub Repository containing the code

J-unit assert method

AmigosCode tutorial on unit testing

Happy coding!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

--

--

Mercy Jemosop

Software Developer. I am open to job referrals. connect with me on twitter @kipyegon_mercy