SpringBoot使用MockMvc進(jìn)行單元測(cè)試的實(shí)例代碼
引言
在Spring Boot應(yīng)用程序中,使用MockMvc進(jìn)行單元測(cè)試是一種有效的方式,可以驗(yàn)證控制器的行為和API的正確性。在這篇博客中,我們將介紹如何使用MockMvc對(duì)用戶控制器(UserController)進(jìn)行測(cè)試,該控制器涉及用戶信息的增刪改查操作。
UserController測(cè)試類(lèi)
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() {
// 在測(cè)試前初始化一些數(shù)據(jù),或者使用Mockito進(jìn)行一些mock設(shè)置
}
@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());
}
}
解釋和注意事項(xiàng)
- MockMvc的注入:
@Autowired注解用于將MockMvc實(shí)例注入測(cè)試類(lèi)中。 - 數(shù)據(jù)初始化: 使用
@Before注解的setUp方法,可以在測(cè)試前進(jìn)行一些數(shù)據(jù)初始化或使用Mockito進(jìn)行一些mock設(shè)置。 - 測(cè)試方法: 每個(gè)測(cè)試方法使用MockMvc執(zhí)行相應(yīng)的HTTP請(qǐng)求,并使用斷言驗(yàn)證控制器的響應(yīng)是否符合預(yù)期。
- 數(shù)據(jù)序列化:
ObjectMapper負(fù)責(zé)將對(duì)象序列化為JSON,以便在POST和PUT請(qǐng)求中傳遞。
以下附上完整代碼
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;
// 查詢(xún)所有用戶
@GetMapping("/getAllUsers")
public List<User> getAllUsers() {
return userService.getAllUsers();
}
// 根據(jù)用戶ID查詢(xún)用戶
@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);
}
// 根據(jù)用戶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 {
// 查詢(xún)所有用戶
List<User> getAllUsers();
// 根據(jù)用戶ID查詢(xún)用戶
User getUserById(Long userId);
// 添加用戶
User addUser(User user);
// 更新用戶信息
User updateUser(User user);
// 根據(jù)用戶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 實(shí)現(xiàn)類(lèi)
*/
@Service
@AllArgsConstructor // Lombok 自動(dòng)生成構(gòu)造函數(shù)
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);
}
實(shí)體類(lèi):
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>
<!-- 查詢(xún)所有用戶 -->
<select id="getAllUsers" resultMap="BaseResultMap">
SELECT *
FROM user;
</select>
<!-- 根據(jù)用戶ID查詢(xún)用戶 -->
<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>
<!-- 根據(jù)用戶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 # 配置駝峰命名規(guī)則
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進(jìn)行單元測(cè)試的實(shí)例代碼的詳細(xì)內(nèi)容,更多關(guān)于SpringBoot MockMvc單元測(cè)試的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Java創(chuàng)建數(shù)組的3種方式代碼舉例
數(shù)組是相同類(lèi)型數(shù)據(jù)的有序集合,數(shù)組描述的是若干個(gè)相同類(lèi)型的數(shù)據(jù)按照一定的先后次序排列組合而成,其中每一個(gè)數(shù)據(jù)稱(chēng)為數(shù)組的元素,可以通過(guò)下標(biāo)進(jìn)行訪問(wèn),這篇文章主要給大家介紹了關(guān)于Java創(chuàng)建數(shù)組的3種方式,需要的朋友可以參考下2024-01-01
Springboot如何優(yōu)雅高效的清除Redis中的業(yè)務(wù)key
這篇文章主要為大家詳細(xì)介紹了Springboot如何優(yōu)雅高效的清除Redis中的業(yè)務(wù)key,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2025-05-05
redisson特性及優(yōu)雅實(shí)現(xiàn)示例
這篇文章主要為大家介紹了redisson特性及優(yōu)雅實(shí)現(xiàn)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-11-11
Swagger中@API?tags中含有中文異常問(wèn)題的解決
這篇文章主要介紹了Swagger中@API?tags中含有中文異常問(wèn)題的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教。2022-01-01
mybatis 返回Map類(lèi)型key改為小寫(xiě)的操作
這篇文章主要介紹了mybatis 返回Map類(lèi)型key改為小寫(xiě)的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-12-12

