Spring Boot MockMVC Testing with Example Project
Last Updated :
09 Oct, 2022
In a Spring Boot project, we have to test the web layer. For that, we can use MockMVC. In this tutorial, let us see how to do that by having a sample GeekEmployee bean and writing the business logic as well as the test cases for it.
Example Project
Project Structure:
This is a maven project. Let's start with
pom.xml
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
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.3.4.RELEASE</version>
<relativePath/>
</parent>
<groupId>com.gfg</groupId>
<artifactId>test-springmvc</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>test-springmvc</name>
<description>Sample Spring Boot</description>
<properties>
<java.version>11</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</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>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
First, let's go with the bean class
GeekEmployee.java
Java
public class GeekEmployee {
private Long employeeId;
private String firstName;
private String lastName;
private int salary;
public int getSalary() {
return salary;
}
public void setSalary(int salary) {
this.salary = salary;
}
public GeekEmployee(String firstName, String lastName, int salary) {
this.firstName = firstName;
this.lastName = lastName;
this.salary = salary;
}
public Long getEmployeeId() {
return employeeId;
}
public void setEmployeeId(Long employeeId) {
this.employeeId = employeeId;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
}
As employeeId is auto-generated, let us create that via
GeekEmployeeIdGenerator.java
Java
public class GeekEmployeeIdGenerator {
private static long employeeId = 1000;
public static synchronized long value() {
return employeeId++;
}
}
Service file where we can write our business logic
GeekEmployeeService.java
Java
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import org.springframework.stereotype.Service;
import com.gfg.gfgsample.domain.GeekEmployee;
import com.gfg.gfgsample.util.GeekEmployeeIdGenerator;
@Service
public class GeekEmployeeService {
Map<Long, GeekEmployee> geekEmployees = new HashMap<>();
// Return all geekEmployees
public Collection<GeekEmployee> findAll(){
return geekEmployees.values();
}
// Find the geekEmployee with this id
public Optional<GeekEmployee> findById(Long employeeId) {
GeekEmployee geekEmployee = null;
if (geekEmployees.containsKey(employeeId)) geekEmployee = geekEmployees.get(employeeId);
return Optional.ofNullable(geekEmployee);
}
// Save a new GeekEmployee
public GeekEmployee save(GeekEmployee geekEmployee) {
geekEmployee.setEmployeeId(GeekEmployeeIdGenerator.value());
geekEmployees.put(geekEmployee.getEmployeeId(), geekEmployee);
return geekEmployee;
}
// Update the GeekEmployee with this id
public Optional<GeekEmployee> update(GeekEmployee geekEmployee) {
GeekEmployee geekEmployee1 = geekEmployees.get(geekEmployee.getEmployeeId());
if (geekEmployee1 != null) {
geekEmployees.put(geekEmployee.getEmployeeId(), geekEmployee);
geekEmployee1 = geekEmployees.get(geekEmployee.getEmployeeId());
}
return Optional.ofNullable(geekEmployee1);
}
// Delete GeekEmployee with this id
public Optional<GeekEmployee> delete(Long employeeId) {
GeekEmployee geekEmployee1 = geekEmployees.get(employeeId);
if (geekEmployee1 != null) {
geekEmployees.remove(employeeId);
}
return Optional.ofNullable(geekEmployee1);
}
}
GeekEmployeeMvcController.java
Java
package com.gfg.gfgsample.web;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import com.gfg.gfgsample.service.GeekEmployeeService;
@Controller
@RequestMapping("mvc")
public class GeekEmployeeMvcController {
private final GeekEmployeeService geekEmployeeService;
public GeekEmployeeMvcController(GeekEmployeeService geekEmployeeService) {
this.geekEmployeeService = geekEmployeeService;
}
@GetMapping("geekemployees")
public String getGeekEmployees(Model model) {
model.addAttribute("geekemployees", geekEmployeeService.findAll());
return "geekemployee-list";
}
}
GeekEmployeeRestController.java
Java
import java.net.URI;
import java.util.Collection;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.support.ServletUriComponentsBuilder;
import com.gfg.gfgsample.domain.GeekEmployee;
import com.gfg.gfgsample.service.GeekEmployeeService;
import com.gfg.gfgsample.util.GeekEmployeeIdGenerator;
@RestController
@RequestMapping("geekemployees")
public class GeekEmployeeRestController {
private final GeekEmployeeService geekEmployeeService;
public GeekEmployeeRestController(GeekEmployeeService service) {
this.geekEmployeeService = service;
}
@GetMapping
Collection<GeekEmployee> readGeekEmployees(){
return this.geekEmployeeService.findAll();
}
@GetMapping("/{id}")
GeekEmployee readGeekEmployee(@PathVariable Long id) {
return this.geekEmployeeService.findById(id)
.orElseThrow(GeekEmployeeNotFoundException::new);
}
@PostMapping
ResponseEntity<?> addEmployee(@RequestBody GeekEmployee geekEmployee){
// Hack to get Mockito test to work
// Will fix this soon
// When not running JUnit tests
// These statements should be commented out
// and the statements below should be uncommented
this.geekEmployeeService.save(geekEmployee);
URI location = ServletUriComponentsBuilder
.fromCurrentRequest()
.path("/{id}")
.buildAndExpand(GeekEmployeeIdGenerator.value())
.toUri();
return ResponseEntity.created(location).build();
}
@PutMapping
GeekEmployee updateEmployee(@RequestBody GeekEmployee geekEmployee) {
return this.geekEmployeeService.update(geekEmployee)
.orElseThrow(GeekEmployeeNotFoundException::new);
}
@DeleteMapping("/{id}")
void deleteStudent(@PathVariable Long id) {
this.geekEmployeeService.delete(id)
.orElseThrow(GeekEmployeeNotFoundException::new);
}
@ResponseStatus(HttpStatus.NOT_FOUND)
class GeekEmployeeNotFoundException extends RuntimeException {
private static final long serialVersionUID = 1L;
public GeekEmployeeNotFoundException() {
super("Employee does not exist");
}
}
}
Start up the file that can run as the java application
TestSpringmvcApplication.java
Java
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import com.gfg.gfgsample.domain.GeekEmployee;
import com.gfg.gfgsample.service.GeekEmployeeService;
@SpringBootApplication
public class TestSpringmvcApplication {
public static void main(String[] args) {
SpringApplication.run(TestSpringmvcApplication.class, args);
}
@Bean
CommandLineRunner init(GeekEmployeeService geekEmployeeService) {
return args -> {
geekEmployeeService.save(new GeekEmployee("Rachel", "Green", 100000));
geekEmployeeService.save(new GeekEmployee("Monica", "Geller", 40000));
geekEmployeeService.save(new GeekEmployee("Phoebe", "", 45000));
};
}
}
geekemployee-list.html
HTML
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org">
<head>
<title>Employee List</title>
<!-- Latest compiled and minified CSS -->
<link rel="stylesheet"
href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css"
integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u"
crossorigin="anonymous" />
</head>
<body>
<div class="container">
<div class="page-header">
<h1>Employee List</h1>
</div>
<div class="container">
<div class="column">
<table class="table datatable">
<tr>
<th>First Name</th>
<th>Last Name</th>
<th>Salary</th>
</tr>
<tr th:each="geekemployee : ${geekemployees}">
<td th:text="${geekemployee.firstName}">Joe</td>
<td th:text="${geekemployee.lastName}">Tribiani</td>
<td th:text="${geekemployee.salary}">100000</td>
</tr>
</table>
</div>
</div>
</div>
</body>
</html>
After running the spring application, our console is as follows
Output on mvc/geekemployees
Testing Part:
GeekEmployeeMvcWebTest.java
Java
import static org.mockito.Mockito.when;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.model;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.view;
import java.util.List;
import org.hamcrest.Matchers;
import org.junit.jupiter.api.Test;
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.test.web.servlet.MockMvc;
import com.gfg.gfgsample.domain.GeekEmployee;
import com.gfg.gfgsample.service.GeekEmployeeService;
@WebMvcTest(controllers = GeekEmployeeMvcController.class)
class GeekEmployeeMvcWebTest {
@Autowired
MockMvc mockMvc;
@MockBean
GeekEmployeeService geekEmployeeService;
@Test
void checkForGeekEmployeeListView() throws Exception {
GeekEmployee ge1 = new GeekEmployee("Rachel", "Green", 50000);
GeekEmployee ge2 = new GeekEmployee("Monica", "Geller", 40000);
GeekEmployee ge3 = new GeekEmployee("Phoebe", "", 45000);
List<GeekEmployee> geekEmployeeList = List.of(ge1, ge2, ge3);
when(geekEmployeeService.findAll()).thenReturn(geekEmployeeList);
this.mockMvc.perform(get("/mvc/geekemployees"))
.andExpect(status().isOk())
.andExpect(view().name("geekemployee-list"))
.andExpect(model().attribute("geekemployees", geekEmployeeList))
.andExpect(model().attribute("geekemployees", Matchers.hasSize(3)))
.andDo(print());
}
}
Testcase Output:
GeekEmployeeRestWebTest.java
Java
import static org.hamcrest.CoreMatchers.containsString;
import static org.mockito.Mockito.when;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import java.util.Optional;
import org.junit.jupiter.api.Test;
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.test.web.servlet.MockMvc;
import com.gfg.gfgsample.domain.GeekEmployee;
import com.gfg.gfgsample.service.GeekEmployeeService;
@WebMvcTest(controllers = GeekEmployeeRestController.class)
class GeekEmployeeRestWebTest {
@Autowired
MockMvc mockMvc;
@MockBean
GeekEmployeeService geekEmployeeService;
@Test
void whenReadGeekEmployee_returnJsonContent() throws Exception {
GeekEmployee rachel = new GeekEmployee("Rachel", "Green", 100000);
rachel.setEmployeeId(1000L);
when(geekEmployeeService.findById(1000L)).thenReturn(Optional.of(rachel));
this.mockMvc.perform(get("/geekemployees/1000"))
.andExpect(status().isOk())
.andExpect(content().string(containsString(
"{\"employeeId\":1000,\"firstName\":\"Rachel\",\"lastName\":\"Green\",\"salary\":100000}")))
.andDo(print());
}
}
Testcase Output:
Similar Reads
Spring Boot | How to consume string messages using Apache Kafka
Apache Kafka is a publish-subscribe messaging queue used for real-time streams of data. A messaging queue lets you send messages between processes, applications, and servers. In this article we will see how to send string messages from apache kafka to the console of a spring boot application. Appro
3 min read
Spring Boot | How to publish String messages on Apache Kafka
Apache Kafka is a publish-subscribe messaging system. A messaging queue lets you send messages between processes, applications, and servers. In this article, we will see how to send string messages to Apache Kafka in a spring boot application. In order to learn how to create a spring boot project, r
2 min read
Spring Boot | How to publish JSON messages on Apache Kafka
Apache Kafka is a publish-subscribe messaging system. A messaging queue lets you send messages between processes, applications, and servers. In this article, we will see how to send JSON messages to Apache Kafka in a spring boot application. In order to learn how to create a spring boot project, ref
4 min read
Spring Boot - Consume JSON Object From Kafka Topics
Apache Kafka is a publish-subscribe messaging system. A messaging system lets someone is sending messages between processes, applications, and servers. Broadly Speaking, Apache Kafka is software where topics (A topic might be a category) can be defined and further processed. Applications may connect
4 min read
Spring Boot Kafka Producer Example
Spring Boot is one of the most popular and most used frameworks of Java Programming Language. It is a microservice-based framework and to make a production-ready application using Spring Boot takes very less time. Spring Boot makes it easy to create stand-alone, production-grade Spring-based Applica
3 min read
Spring Boot Kafka Consumer Example
Spring Boot is one of the most popular and most used frameworks of Java Programming Language. It is a microservice-based framework and to make a production-ready application using Spring Boot takes very less time. Spring Boot makes it easy to create stand-alone, production-grade Spring-based Applica
3 min read
Message Compression in Apache Kafka using Spring Boot
Generally, producers send text-based data, such as JSON data. It is essential to apply compression to the producer in this situation. Producer messages are transmitted uncompressed by default. There are two types of Kafka compression. 1. Producer-Level Kafka Compression When compression is enabled o
4 min read
Spring Boot - Create and Configure Topics in Apache Kafka
Topics are a special and essential component of Apache Kafka that are used to organize events or messages. In other words, Kafka Topics enable simple data transmission and reception across Kafka Servers by acting as Virtual Groups or Logs that store messages and events in a logical sequence. In this
2 min read
How to Test Spring Boot Project using ZeroCode?
Zerocode automated testing framework for a REST API project concept is getting seen via this tutorial by taking a sample spring boot maven project. Let us see the dependencies for Zerocode : <dependency> <groupId>org.jsmart</groupId> <artifactId>zerocode-tdd</artifactId
5 min read
Validation in Spring Boot
In this article, via a Gradle project, let us see how to validate a sample application and show the output in the browser. The application is prepared as of type Spring Boot and in this article let us see how to execute via the command line as well. Example Project Project Structure: Â As this is th
5 min read