SpringBoot无Service类时如何用JUnit、Mockito编写Controller测试用例
SpringBoot Controller单元测试实操(无Service层场景)
前置准备
首先确保你的pom.xml(Maven)或build.gradle(Gradle)中已引入SpringBoot测试启动器,里面内置了JUnit、Mockito、MockMvc等所需工具:
<!-- Maven 依赖示例 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency>
你提供的UserRepository代码已经符合JPA规范,我们默认你已经有对应的User实体类,以及直接依赖UserRepository的UserController,先给出参考的Controller示例方便对照:
package com.example.spring; import org.springframework.web.bind.annotation.*; import javax.annotation.Resource; import java.util.List; import java.util.Optional; @RestController @RequestMapping("/users") public class UserController { @Resource private UserRepository userRepository; // 查询所有用户 @GetMapping public List<User> getAllUsers() { return userRepository.findAll(); } // 根据ID查询单个用户 @GetMapping("/{id}") public User getUserById(@PathVariable Integer id) { return userRepository.findById(id).orElse(null); } // 新增用户 @PostMapping public User addUser(@RequestBody User user) { return userRepository.save(user); } }
编写Controller测试用例
我们使用@WebMvcTest注解做Controller切片测试,该注解只会加载Controller层相关Bean,不会启动完整的Spring上下文,速度更快。依赖的Repository我们用Mockito模拟,不需要真实连接数据库。
完整测试代码如下:
package com.example.spring; 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.http.MediaType; import org.springframework.test.web.servlet.MockMvc; import com.fasterxml.jackson.databind.ObjectMapper; import java.util.Arrays; import java.util.Optional; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.when; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; // 指定要测试的Controller类 @WebMvcTest(UserController.class) public class UserControllerTest { // 注入MockMvc,用于模拟发送HTTP请求 @Autowired private MockMvc mockMvc; // 模拟UserRepository,替代真实的Bean注入到Controller中 @MockBean private UserRepository userRepository; // JSON转换工具,用于把对象转成请求的JSON字符串 @Autowired private ObjectMapper objectMapper; // 测试查询所有用户接口 @Test public void testGetAllUsers() throws Exception { // 1. 模拟Repository的返回数据 User user1 = new User(1, "张三", 20); User user2 = new User(2, "李四", 22); when(userRepository.findAll()).thenReturn(Arrays.asList(user1, user2)); // 2. 发送GET请求到/users接口,校验响应结果 mockMvc.perform(get("/users") .contentType(MediaType.APPLICATION_JSON)) .andExpect(status().isOk()) // 校验状态码200 .andExpect(jsonPath("$[0].name").value("张三")) // 校验第一个用户的name字段 .andExpect(jsonPath("$[1].age").value(22)); // 校验第二个用户的age字段 } // 测试根据ID查询用户接口 @Test public void testGetUserById() throws Exception { User mockUser = new User(1, "张三", 20); when(userRepository.findById(1)).thenReturn(Optional.of(mockUser)); mockMvc.perform(get("/users/1") .contentType(MediaType.APPLICATION_JSON)) .andExpect(status().isOk()) .andExpect(jsonPath("$.name").value("张三")); } // 测试新增用户接口 @Test public void testAddUser() throws Exception { User newUser = new User(null, "王五", 25); User savedUser = new User(3, "王五", 25); // 模拟调用save方法时返回存好的带ID的用户 when(userRepository.save(any(User.class))).thenReturn(savedUser); mockMvc.perform(post("/users") .contentType(MediaType.APPLICATION_JSON) // 把新增用户对象转成JSON放到请求体里 .content(objectMapper.writeValueAsString(newUser))) .andExpect(status().isOk()) .andExpect(jsonPath("$.id").value(3)) .andExpect(jsonPath("$.name").value("王五")); } }
核心逻辑说明
@WebMvcTest:SpringBoot提供的切片测试注解,仅加载指定的Controller层组件,适合做Controller单元测试@MockBean:将Mockito模拟的对象注入到Spring上下文中,替换掉真实的Repository实现,不需要操作真实数据库MockMvc:模拟HTTP客户端,直接向Controller发送请求、接收响应,不需要启动Tomcat容器when(...)thenReturn(...):Mockito的核心API,指定调用Mock对象的某个方法时要返回的模拟数据
你可以直接按照这个模板,根据你自己Controller里的接口逻辑调整模拟数据和校验规则即可。
内容的提问来源于stack exchange,提问作者Harshita2002
相关产品推荐
相关产品推荐

