Friday, October 10, 2025
HomeLanguagesJavaSpring Boot MockMVC Testing with Example Project

Spring Boot MockMVC Testing with Example Project

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:

Project Structure

 

This is a maven project. Let’s start with

pom.xml

XML




<?xml version="1.0" encoding="UTF-8"?>
         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




   xmlns:th="http://www.thymeleaf.org">
   <head>
      <title>Employee List</title>
      <!-- Latest compiled and minified CSS -->
      <link rel="stylesheet"
         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:

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:

Testcase Output

 

Dominic
Dominichttp://wardslaus.com
infosec,malicious & dos attacks generator, boot rom exploit philanthropist , wild hacker , game developer,
RELATED ARTICLES

Most Popular

Dominic
32348 POSTS0 COMMENTS
Milvus
87 POSTS0 COMMENTS
Nango Kala
6715 POSTS0 COMMENTS
Nicole Veronica
11878 POSTS0 COMMENTS
Nokonwaba Nkukhwana
11941 POSTS0 COMMENTS
Shaida Kate Naidoo
6837 POSTS0 COMMENTS
Ted Musemwa
7097 POSTS0 COMMENTS
Thapelo Manthata
6792 POSTS0 COMMENTS
Umr Jansen
6791 POSTS0 COMMENTS