SpringBoot使用MockMvc進(jìn)行單元測試的實例代碼
引言
在Spring Boot應(yīng)用程序中,使用MockMvc進(jìn)行單元測試是一種有效的方式,可以驗證控制器的行為和API的正確性。在這篇博客中,我們將介紹如何使用MockMvc對用戶控制器(UserController)進(jìn)行測試,該控制器涉及用戶信息的增刪改查操作。
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() { // 在測試前初始化一些數(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()); } }
解釋和注意事項
- MockMvc的注入:
@Autowired
注解用于將MockMvc實例注入測試類中。 - 數(shù)據(jù)初始化: 使用
@Before
注解的setUp
方法,可以在測試前進(jìn)行一些數(shù)據(jù)初始化或使用Mockito進(jìn)行一些mock設(shè)置。 - 測試方法: 每個測試方法使用MockMvc執(zhí)行相應(yīng)的HTTP請求,并使用斷言驗證控制器的響應(yīng)是否符合預(yù)期。
- 數(shù)據(jù)序列化:
ObjectMapper
負(fù)責(zé)將對象序列化為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(); } // 根據(jù)用戶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); } // 根據(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 { // 查詢所有用戶 List<User> getAllUsers(); // 根據(jù)用戶ID查詢用戶 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 實現(xiàn)類 */ @Service @AllArgsConstructor // Lombok 自動生成構(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); }
實體類:
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> <!-- 根據(jù)用戶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> <!-- 根據(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)行單元測試的實例代碼的詳細(xì)內(nèi)容,更多關(guān)于SpringBoot MockMvc單元測試的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Java getResource()如何獲取class文件目錄位置
這篇文章主要介紹了Java getResource()如何獲取class文件目錄位置,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-12-12SpringBoot中ApplicationEvent和ApplicationListener用法小結(jié)
這篇文章介紹SpringBoot中ApplicationEvent用法,注意ApplicationEvent和MQ隊列雖然實現(xiàn)的功能相似,但是MQ還是有其不可替代性的,最本質(zhì)的區(qū)別就是MQ可以用于不同系統(tǒng)之間的消息發(fā)布,而SpringEvent這種模式只能在一個系統(tǒng)中,需要的朋友可以參考下2023-03-03springboot使用redisTemplate操作lua腳本
本文主要介紹了springboot使用redisTemplate操作lua腳本,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-08-08Java之?dāng)?shù)組在指定位置插入元素實現(xiàn)
本文主要介紹了Java之?dāng)?shù)組在指定位置插入元素實現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-01-01Hikari?數(shù)據(jù)庫連接池內(nèi)部源碼實現(xiàn)的小細(xì)節(jié)
這篇文章主要介紹了Hikari?數(shù)據(jù)庫連接池內(nèi)部源碼實現(xiàn)的小細(xì)節(jié),具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-02-02Java JDK動態(tài)代理(AOP)用法及實現(xiàn)原理詳解
在本篇文章了小編給大家整理的是一篇關(guān)于Java JDK動態(tài)代理(AOP)用法及實現(xiàn)原理詳解內(nèi)容,有需要的朋友們可以參考學(xué)習(xí)下。2020-10-10