如何使用Mockito测试Spring中的Controller方法?
我来帮你搞定用Mockito测试这个Spring Controller的addAccount方法!首先,咱们得明确这个方法的核心逻辑分支:参数校验失败、用户名已存在、账号正常创建成功,这几个场景都得覆盖到。我会用Spring Boot Test结合Mockito来写测试,这样能更贴近真实的运行环境。
前置依赖
首先确保你的项目依赖里包含Spring Boot Test(它已经内置了Mockito和MockMvc,不用额外引入):
<!-- Maven示例 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency>
测试类基础结构
先创建对应的测试类,用@WebMvcTest只加载Controller层Bean,配合@MockBean模拟依赖的accountRepository和bCryptPasswordEncoder:
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 static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.*; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; // 替换成你的实际Controller类名 @WebMvcTest(AccountController.class) public class AccountControllerTest { @Autowired private MockMvc mockMvc; // 用来模拟HTTP请求 @MockBean private AccountRepository accountRepository; // 模拟Repository依赖 @MockBean private BCryptPasswordEncoder bCryptPasswordEncoder; // 模拟密码加密器 }
分场景测试示例
1. 测试参数不合法的情况
当传入的Account为null、userName为空或userPass为空时,方法应该返回参数错误响应:
子场景:Account对象为null
@Test public void addAccount_WhenAccountIsNull_ReturnsBadRequest() throws Exception { mockMvc.perform(post("/add") .contentType(MediaType.APPLICATION_JSON) .content("null")) // 传入null的请求体 .andExpect(status().isBadRequest()); }
子场景:userName为空
@Test public void addAccount_WhenUserNameIsNull_ReturnsBadRequest() throws Exception { String invalidAccountJson = "{\"userName\": null, \"userPass\": \"123456\"}"; mockMvc.perform(post("/add") .contentType(MediaType.APPLICATION_JSON) .content(invalidAccountJson)) .andExpect(status().isBadRequest()); }
2. 测试用户名已存在的情况
当accountRepository.countUserName()返回大于0的数值时,方法应该返回BAD_REQUEST和"Account":
@Test public void addAccount_WhenUserNameExists_ReturnsBadRequest() throws Exception { String existingAccountJson = "{\"userName\": \"oldUser\", \"userPass\": \"123456\"}"; // Mock用户名已存在的场景 when(accountRepository.countUserName("oldUser")).thenReturn(1L); mockMvc.perform(post("/add") .contentType(MediaType.APPLICATION_JSON) .content(existingAccountJson)) .andExpect(status().isBadRequest()) .andExpect(content().string("Account")); // 验证返回内容 // 确认Repository的方法确实被调用了一次 verify(accountRepository, times(1)).countUserName("oldUser"); }
3. 测试账号添加成功的情况
当参数合法且用户名不存在时,会执行密码加密、保存账号,最终返回成功响应:
@Test public void addAccount_WhenValidAccount_ReturnsSuccess() throws Exception { String validAccountJson = "{\"userName\": \"newUser\", \"userPass\": \"plainPwd\"}"; String mockEncodedPwd = "encodedPwd123"; // Mock用户名不存在 when(accountRepository.countUserName("newUser")).thenReturn(0L); // Mock密码加密结果 when(bCryptPasswordEncoder.encode("plainPwd")).thenReturn(mockEncodedPwd); // Mock账号保存操作(无返回值) doNothing().when(accountRepository).AccountSaveTo(any(Account.class)); mockMvc.perform(post("/add") .contentType(MediaType.APPLICATION_JSON) .content(validAccountJson)) .andExpect(status().isOk()); // 替换成你方法实际返回的成功状态码 // 验证所有依赖方法都被正确调用 verify(accountRepository, times(1)).countUserName("newUser"); verify(bCryptPasswordEncoder, times(1)).encode("plainPwd"); verify(accountRepository, times(1)).AccountSaveTo(any(Account.class)); }
小提示
- 原方法里的
bCryptPasswordEncoder.encod()应该是笔误,正确方法名是encode(),测试时要对应上; - 可以用
ObjectMapper序列化Account对象生成JSON,避免手动写JSON出错:ObjectMapper objectMapper = new ObjectMapper(); String accountJson = objectMapper.writeValueAsString(new Account("newUser", "plainPwd"));
内容的提问来源于stack exchange,提问作者martine
相关产品推荐
相关产品推荐

