SpringBoot使用MockMvc进行单元测试的实例代码

 更新时间:2024年01月19日 11:29:02   作者:冷风扇666  
在Spring Boot应用程序中,使用MockMvc进行单元测试是一种有效的方式,可以验证控制器的行为和API的正确性,在这篇博客中,我们将介绍如何使用MockMvc对用户控制器进行测试,感兴趣的朋友可以参考下

引言

在Spring Boot应用程序中,使用MockMvc进行单元测试是一种有效的方式,可以验证控制器的行为和API的正确性。在这篇博客中,我们将介绍如何使用MockMvc对用户控制器(UserController)进行测试,该控制器涉及用户信息的增删改查操作。

UserController测试类

package com.lfsun.mockmvc;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.lfsun.mockmvc.entity.User;
import com.lfsun.mockmvc.service.UserService;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.MediaType;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;

import java.util.Arrays;
import java.util.List;

import static org.mockito.Mockito.when;
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

@RunWith(SpringRunner.class)
@SpringBootTest
@AutoConfigureMockMvc
public class UserControllerTest {

    @Autowired
    private MockMvc mockMvc;

    @Autowired
    private UserService userService;

    @Autowired
    private ObjectMapper objectMapper;

    @Before
    public void setUp() {
        // 在测试前初始化一些数据,或者使用Mockito进行一些mock设置
    }

    @Test
    public void getAllUsersTest() throws Exception {
        mockMvc.perform(MockMvcRequestBuilders.get("/user/getAllUsers"))
                .andExpect(status().isOk())
                .andExpect(jsonPath("$").isArray())
                .andExpect(jsonPath("$.length()").value(userService.getAllUsers().size()))
                .andDo(print());
    }

    @Test
    public void getUserByIdTest() throws Exception {
        Long userId = 1L;
        mockMvc.perform(MockMvcRequestBuilders.get("/user/getUserById/{userId}", userId))
                .andExpect(status().isOk())
                .andExpect(jsonPath("$.userId").value(userId))
                .andDo(print());
    }

    @Test
    public void addUserTest() throws Exception {
        User user = new User();
        user.setUsername("testUser");
        user.setEmail("test@lfsun.com");

        mockMvc.perform(MockMvcRequestBuilders.post("/user/addUser")
                        .contentType(MediaType.APPLICATION_JSON)
                        .content(objectMapper.writeValueAsString(user)))
                .andExpect(status().isOk())
                .andExpect(jsonPath("$.username").value("testUser"))
                .andExpect(jsonPath("$.email").value("test@lfsun.com"))
                .andDo(print());
    }

    @Test
    public void updateUserTest() throws Exception {
        Long userId = 1L;
        User updatedUser = new User();
        updatedUser.setUserId(userId);
        updatedUser.setUsername("updatedUser");
        updatedUser.setEmail("updated@lfsun.com");

        mockMvc.perform(MockMvcRequestBuilders.put("/user/updateUser")
                        .contentType(MediaType.APPLICATION_JSON)
                        .content(objectMapper.writeValueAsString(updatedUser)))
                .andExpect(status().isOk())
                .andExpect(jsonPath("$.userId").value(userId))
                .andExpect(jsonPath("$.username").value("updatedUser"))
                .andExpect(jsonPath("$.email").value("updated@lfsun.com"))
                .andDo(print());
    }

    @Test
    public void deleteUserTest() throws Exception {
        Long userId = 1L;
        mockMvc.perform(MockMvcRequestBuilders.delete("/user/deleteUser/{userId}", userId))
                .andExpect(status().isOk())
                .andDo(print());
    }
}

解释和注意事项

  1. MockMvc的注入: @Autowired 注解用于将MockMvc实例注入测试类中。
  2. 数据初始化: 使用 @Before 注解的 setUp 方法,可以在测试前进行一些数据初始化或使用Mockito进行一些mock设置。
  3. 测试方法: 每个测试方法使用MockMvc执行相应的HTTP请求,并使用断言验证控制器的响应是否符合预期。
  4. 数据序列化: ObjectMapper 负责将对象序列化为JSON,以便在POST和PUT请求中传递。

以下附上完整代码

controller:

package com.lfsun.mockmvc.controller;


import com.lfsun.mockmvc.entity.User;
import com.lfsun.mockmvc.service.UserService;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*;

import java.util.List;

/**
 * 用户 Controller
 *
 * @author CL
 */
@RestController
@RequestMapping(value = "/user")
@RequiredArgsConstructor
public class UserController {

    private final UserService userService;

    // 查询所有用户
    @GetMapping("/getAllUsers")
    public List<User> getAllUsers() {
        return userService.getAllUsers();
    }

    // 根据用户ID查询用户
    @GetMapping("/getUserById/{userId}")
    public User getUserById(@PathVariable Long userId) {
        return userService.getUserById(userId);
    }

    // 添加用户
    @PostMapping("/addUser")
    public User addUser(@RequestBody User user) {
        return userService.addUser(user);
    }

    // 更新用户信息
    @PutMapping("/updateUser")
    public User updateUser(@RequestBody User user) {
        return userService.updateUser(user);
    }

    // 根据用户ID删除用户
    @DeleteMapping("/deleteUser/{userId}")
    public void deleteUser(@PathVariable Long userId) {
        userService.deleteUser(userId);
    }
}

service、serviceimpl

package com.lfsun.mockmvc.service;


import com.lfsun.mockmvc.entity.User;

import java.util.List;

/**
 * 用户 Service 接口
 */
public interface UserService {

    // 查询所有用户
    List<User> getAllUsers();

    // 根据用户ID查询用户
    User getUserById(Long userId);

    // 添加用户
    User addUser(User user);

    // 更新用户信息
    User updateUser(User user);

    // 根据用户ID删除用户
    void deleteUser(Long userId);
}
package com.lfsun.mockmvc.service.impl;

import com.lfsun.mockmvc.entity.User;
import com.lfsun.mockmvc.mapper.UserMapper;
import com.lfsun.mockmvc.service.UserService;
import lombok.AllArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * 用户 Service 实现类
 */
@Service
@AllArgsConstructor  // Lombok 自动生成构造函数
public class UserServiceImpl implements UserService {

    private final UserMapper userMapper;

    @Override
    public List<User> getAllUsers() {
        return userMapper.getAllUsers();
    }

    @Override
    public User getUserById(Long userId) {
        return userMapper.getUserById(userId);
    }

    @Override
    public User addUser(User user) {
        userMapper.addUser(user);
        return user;
    }

    @Override
    public User updateUser(User user) {
        userMapper.updateUser(user);
        return user;
    }

    @Override
    public void deleteUser(Long userId) {
        userMapper.deleteUser(userId);
    }
}

mapper

package com.lfsun.mockmvc.mapper;

import com.lfsun.mockmvc.entity.User;
import org.apache.ibatis.annotations.*;

import java.util.List;

/**
 * 用户 Mapper 接口
 */
@Mapper
public interface UserMapper {

    List<User> getAllUsers();

    User getUserById(Long userId);

    void addUser(User user);

    void updateUser(User user);

    void deleteUser(Long userId);
}

实体类:

package com.lfsun.mockmvc.entity;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
    private Long userId;
    private String username;
    private String email;

}

xml

<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="com.lfsun.mockmvc.mapper.UserMapper">

    <resultMap id="BaseResultMap" type="com.lfsun.mockmvc.entity.User">
        <id column="user_id" property="userId" jdbcType="BIGINT"/>
        <result column="username" property="username" jdbcType="VARCHAR"/>
        <result column="email" property="email" jdbcType="VARCHAR"/>
    </resultMap>

    <!-- 查询所有用户 -->
    <select id="getAllUsers" resultMap="BaseResultMap">
        SELECT *
        FROM user;
    </select>

    <!-- 根据用户ID查询用户 -->
    <select id="getUserById" resultMap="BaseResultMap" parameterType="java.lang.Long">
        SELECT *
        FROM user
        WHERE user_id = #{userId};
    </select>

    <!-- 添加用户 -->
    <insert id="addUser" parameterType="com.lfsun.mockmvc.entity.User">
        INSERT INTO user (username, email)
        VALUES (#{username}, #{email});
    </insert>

    <!-- 更新用户信息 -->
    <update id="updateUser" parameterType="com.lfsun.mockmvc.entity.User">
        UPDATE user
        SET username = #{username},
            email    = #{email}
        WHERE user_id = #{userId};
    </update>

    <!-- 根据用户ID删除用户 -->
    <delete id="deleteUser" parameterType="java.lang.Long">
        DELETE
        FROM user
        WHERE user_id = #{userId};
    </delete>

</mapper>

配置

spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://127.0.0.1:3306/mockmvc?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=UTC&rewriteBatchedStatements=true
    username: root
    password: 123321

mybatis:
  mapper-locations: classpath:/mapper/*.xml  # 指定 MyBatis mapper 文件的位置
  configuration:
    map-underscore-to-camel-case: true  # 配置驼峰命名规则

maven

<?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.14</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.lfsun</groupId>
    <artifactId>lfsun-study-mockmvc</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>lfsun-study-mockmvc</name>
    <description>lfsun-study-mockmvc</description>
    <properties>
        <java.version>17</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.23</version>
            <scope>compile</scope>
        </dependency>

        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>1.3.2</version>
        </dependency>

    </dependencies>

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

</project>

最后

以上就是SpringBoot使用MockMvc进行单元测试的实例代码的详细内容,更多关于SpringBoot MockMvc单元测试的资料请关注脚本之家其它相关文章!

相关文章

  • Spring Boot如何整合FreeMarker模板引擎

    Spring Boot如何整合FreeMarker模板引擎

    这篇文章主要介绍了Spring Boot如何整合FreeMarker模板引擎,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-10-10
  • java并发请求下数据插入重复问题的解决方法

    java并发请求下数据插入重复问题的解决方法

    现在遇到一个项目,移动设备存储数据,然后一起上传,那就出现了许多重复数据,这篇文章主要给大家介绍了关于java并发请求下数据插入重复问题的解决方法,需要的朋友可以参考下
    2021-11-11
  • java 获取路径的各种方法(总结)

    java 获取路径的各种方法(总结)

    下面小编就为大家带来一篇java 获取路径的各种方法(总结)。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2016-08-08
  • SpringBoot JPA懒加载失效的解决方案(亲测有效)

    SpringBoot JPA懒加载失效的解决方案(亲测有效)

    这篇文章主要介绍了SpringBoot JPA懒加载失效的解决方案(亲测有效),具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-08-08
  • 详解MyBatis中主键回填的两种实现方式

    详解MyBatis中主键回填的两种实现方式

    这篇文章主要介绍了详解MyBatis中主键回填的两种实现方式,主键回填其实是一个非常常见的需求,特别是在数据添加的过程中,我们经常需要添加完数据之后,需要获取刚刚添加的数据 id,有兴趣的可以参考一下
    2019-04-04
  • Java设计模式之解释器模式

    Java设计模式之解释器模式

    这篇文章介绍了Java设计模式之解释器模式,文中通过示例代码介绍的非常详细。对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-10-10
  • SpringBoot yml配置文件调用过程解析

    SpringBoot yml配置文件调用过程解析

    这篇文章主要介绍了SpringBoot yml配置文件调用过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-11-11
  • SSH框架网上商城项目第3战之使用EasyUI搭建后台页面框架

    SSH框架网上商城项目第3战之使用EasyUI搭建后台页面框架

    SSH框架网上商城项目第3战之使用EasyUI搭建后台页面框架,讨论两种搭建方式:基于frameset和基于easyUI,感兴趣的小伙伴们可以参考一下
    2016-05-05
  • Spring Boot详解配置文件的用途与用法

    Spring Boot详解配置文件的用途与用法

    SpringBoot项目是一个标准的Maven项目,它的配置文件需要放在src/main/resources/下,其文件名必须为application,其存在两种文件形式,分别是properties和yaml(或者yml)文件
    2022-06-06
  • Java并发之原子性 有序性 可见性及Happen Before原则

    Java并发之原子性 有序性 可见性及Happen Before原则

    一提到happens-before原则,就让人有点“丈二和尚摸不着头脑”。这个涵盖了整个JMM中可见性原则的规则,究竟如何理解,把我个人一些理解记录下来。下面可以和小编一起学习Java 并发四个原则
    2021-09-09

最新评论