Spring Boot + Mockito simple application with 100% code coverage

In this article, we will show you a sample Spring example to demonstrate test methods for Controllers, Service, and Repository, And code coverage analysis using the EclEmma plugin.



Technologies used:

  • Spring Boot 2.1.1.RELEASE
  • Spring MVC 5.1.1.RELEASE
  • H2DB 1.4.197
  • Mockito 2
  • Maven
  • EclEmma plugin
  • Junit 4
A quick overview of  Spring Boot, Mockito, and EclEmma plugin

Spring boot:

Spring boot to develop REST web services and microservices. Spring Boot has taken the Spring framework to the next level. It has drastically reduced the configuration and setup time required for spring projects. We can set up a project with almost zero configuration and start building the things that actually matter to your application.

Mockito:

Mockito is a mocking framework, a JAVA-predicated library that is utilized for efficacious unit testing of JAVA applications. Mockito is utilized to mock interfaces so that a dummy functionality can be integrated into a mock interface that can be utilized in unit testing.

EclEmma:

EclEmma is a free Java code coverage implement for Eclipse, available under the Eclipse Public License. It brings code coverage analysis directly into the Eclipse workbench

Code Coverage:

Code coverage is the percentage of code that is covered by automated tests. Code coverage quantification simply determines which statements in a body of code have been executed through a test run, and which statements expressions have not.

Let see the following Spring boot MVC web application, and how to perform the unit test with Mockito framework and Junit 4, and code coverage with the EclEmma plugin.

Project Structure


Maven[pom.xml]

<?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
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>com.knf.dev</groupId>
<artifactId>spring_mockito_example</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>

<name>spring_mockito_example</name>
<description>Demo project for Spring Boot</description>

<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.1.RELEASE</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.
outputEncoding>
<java.version>1.8</java.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>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>

<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>


</project>

Entity class[User.class]

package com.knf.dev.mockito.entity;

import javax.persistence.*;
import javax.validation.constraints.Size;

@Entity
@Table(name = "user")
public class User {

@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE)
private Integer id;

@Size(min = 3, max = 20)
private String name;

public Integer getId() {
return id;
}

public void setId(Integer id) {
this.id = id;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}
}

Repository layer[UserRepository.class]

package com.knf.dev.mockito.repository;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

import com.knf.dev.mockito.entity.User;

@Repository
public interface UserRepository extends JpaRepository<User, Integer> {

public User findByName(String name);

}

Service Layer[UserService.class]

package com.knf.dev.mockito.service;

import com.knf.dev.mockito.entity.User;

public interface UserService {

public User getUserByName(String name);
}

UserServiceImpl.class

package com.knf.dev.mockito.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.knf.dev.mockito.entity.User;
import com.knf.dev.mockito.repository.UserRepository;

@Service
public class UserServiceImpl implements UserService {

@Autowired
private UserRepository userRepository;

@Override
public User getUserByName(String name) {
return userRepository.findByName(name);
}

}

RestController[UserRestController.class]

package com.knf.dev.mockito.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.knf.dev.mockito.entity.User;
import com.knf.dev.mockito.service.UserService;

@RestController
@RequestMapping("/api")
public class UserRestController {

@Autowired
private UserService userService;

@GetMapping("/user")
public User getAllEmployees() {
return userService.getUserByName("sibin");
}

}

Main class[MockitoApplication.class]

package com.knf.dev.mockito;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class MockitoApplication {

public static void main(String[] args) {
SpringApplication.run(MockitoApplication.class, args);
}
}

Unit testing

UserRepositoryIntegrationTest.class

package com.knf.dev.mockito.repository;

import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.boot.test.autoconfigure.orm.jpa.TestEntityManager;
import org.springframework.test.context.junit4.SpringRunner;

import com.knf.dev.mockito.entity.User;

@RunWith(SpringRunner.class)
@DataJpaTest
public class UserRepositoryIntegrationTest {

@Autowired
private TestEntityManager entityManager;

@Autowired
private UserRepository userRepository;

@Test
public void whenFindByName_thenReturnUser() {
// given
String name = "sibin";
User user = new User();
user.setName(name);
entityManager.persist(user);
entityManager.flush();

// when
User found = userRepository.findByName(user.getName());

// then
Assert.assertNotNull(found);
Assert.assertEquals(found.getName(), name);

}

}

UserServiceImplIntegrationTest.class

package com.knf.dev.mockito.service;

import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.TestConfiguration;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.context.annotation.Bean;
import org.springframework.test.context.junit4.SpringRunner;

import com.knf.dev.mockito.entity.User;
import com.knf.dev.mockito.repository.UserRepository;

@RunWith(SpringRunner.class)
public class UserServiceImplIntegrationTest {

@TestConfiguration
static class UserServiceImplTestContextConfiguration {

@Bean
public UserService userService() {
return new UserServiceImpl();
}
}

@Autowired
private UserService userService;

@MockBean
private UserRepository userRepository;

@Before
public void setUp() {
User user = new User();
user.setName("sibin");
user.setId(1);
Mockito.when(userRepository.findByName(user.getName())).
thenReturn(user);
}

@Test
public void whenValidName_thenEmployeeShouldBeFound() {
String name = "sibin";
User found = userService.getUserByName(name);

Assert.assertEquals(found.getName(), name);
}
}

UserRestControllerIntegrationTest.class

package com.knf.dev.mockito.controller;

import static org.mockito.BDDMockito.given;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.http.MediaType;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;

import com.knf.dev.mockito.entity.User;
import com.knf.dev.mockito.service.UserService;

@RunWith(SpringRunner.class)
@WebMvcTest(UserRestController.class)
public class UserRestControllerIntegrationTest {

@Autowired
private MockMvc mvc;

@MockBean
private UserService service;

@Test
public void givenEmployees_whenGetEmployees_thenReturnJsonArray()
throws Exception {

User user = new User();
user.setName("sibin");

given(service.getUserByName("sibin")).willReturn(user);

mvc.perform(get("/api/user").contentType(MediaType.APPLICATION_JSON)).
andExpect(status().isOk())
.andExpect(jsonPath("$.name").value("sibin"));
}
}

MockitoApplicationTests.class

package com.knf.dev.mockito;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

@RunWith(SpringRunner.class)
@SpringBootTest
public class MockitoApplicationTests {

@Test
public void main() {
MockitoApplication.main(new String[] {});
}

}

Run: Unit test + Code coverage

Step 1: Install the EclEmma plugin from Eclipse Marketplace Client 


Step 2: Right-click on our project[spring_mockito_example] and click coverage As > Junit Test

Step 3: Verify 100 Percent Code Coverage 


Download the source code

                git clone: https://github.com/knowledgefactory4u/mockito_junti.git


Comments