Spring Boot + junit5 + Mockito
Mockito is a mocking framework used for mocking any third party dependency. Unit testing of the classes where the code depends any any third party call such as database call becomes difficult without running the entire application. To avoid that, we use mocking frameworks like Mockito.
In this tutorial, we will create a microservice and write test case by mocking the database calls.
In the below microservice, we have entity class Book and using findAll method of CrudRepository, we are fetching all the available records from the database.
pom.xml for this project
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.4</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<groupId>com.javatrainingschool</groupId>
<artifactId>library-spring-boot</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>library-spring-boot</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
<junit-jupiter.version>5.9.1</junit-jupiter.version>
<mockito.version>4.8.0</mockito.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- junit 5 -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>${junit-jupiter.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
Spring Boot main application
package com.javatraining;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class LibrarySpringBootApplication {
public static void main(String[] args) {
SpringApplication.run(LibrarySpringBootApplication.class, args);
}
}
Entity class
package com.javatraining.entity;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
@Entity
@Table(name = "book")
public class Book {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private int id;
private String name;
private String author;
private int price;
private String status;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public int getPrice() {
return price;
}
public void setPrice(int price) {
this.price = price;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
@Override
public String toString() {
return "Book [id=" + id + ", name=" + name + ", author=" + author + ", price=" + price + ", status=" + status
+ "]";
}
public Book(int id, String name, String author, int price, String status) {
super();
this.id = id;
this.name = name;
this.author = author;
this.price = price;
this.status = status;
}
public Book() {
super();
// TODO Auto-generated constructor stub
}
}
Repository class
package com.javatraining.repository;
import java.util.List;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;
import com.javatraining.entity.Book;
public interface BookRepository extends CrudRepository<Book, Integer>{
public List<Book> findByName(String name);
}
Service class : In the class we have logic, that in every book name we will append ‘-b’. We will verify the same thing in the test case for this class.
package com.javatraining.service;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.javatraining.entity.Book;
import com.javatraining.repository.BookRepository;
@Service
public class BookService {
@Autowired
BookRepository bookRepo;
public List<Book> getAllBooks() {
List<Book> allBooks = (List<Book>) bookRepo.findAll();
allBooks.forEach(b -> b.setName(b.getName() + "-b"));
return allBooks;
}
}
Write Junit5 + mocking with Mockito
Now, we will write the test case for service class.
In the below code, we have mocked the repository interface and method call inside it. And we have returned a mock list whenever database call is encountered.
We have made 3 assertions here. First, that the list is not null. Second, that the name of the book endsWith -b and the name of the book is Learn Java-b.
package com.javatrainingschool;
import static org.mockito.Mockito.when;
import java.util.ArrayList;
import java.util.List;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.springframework.boot.test.context.SpringBootTest;
import com.javatraining.LibrarySpringBootApplication;
import com.javatraining.entity.Book;
import com.javatraining.repository.BookRepository;
import com.javatraining.service.BookService;
@SpringBootTest(classes=LibrarySpringBootApplication.class)
public class BookServiceTest {
@Mock
BookRepository bookRepo;
@InjectMocks
BookService bookService = new BookService();
@Test
public void testGetAllBooks() {
List<Book> books = new ArrayList<>();
Book b = new Book(1, "Learn Java", "Abc", 100, "borrowed");
books.add(b);
when(bookRepo.findAll()).thenReturn(books);
List<Book> result = bookService.getAllBooks();
Assertions.assertNotEquals(null, result);
Assertions.assertTrue(result.get(0).getName().endsWith("-b"));
Assertions.assertEquals("Learn Java-b", result.get(0).getName());
}
}