👉 学会 全新设计的脚手架 ,从此面试不再怕!
不要全部使用 @SpringBootTest
使用 @SpringBootTest
进行单元测试会启动整个 Spring Boot 容器,并引入整个项目的 development&test
依赖。缺点是速度慢、体积大、测试目标不明确、低内聚高耦合。
明确我们要测试的目标是登录功能,所以只要启动 Spring Mvc 的依赖范围就可以了,其他层面的依赖可以用「打桩」来解决。
使用 @WebMvcTest
所以只需要隔离启动 Spring Mvc 环境,即可完成登录功能的测试了。
@WebMvcTest(value = {SignController.class})
@Import({HttpFireWallConfig.class})
class SignMvcTest {
@MockBean private SignService signService;
@MockBean private CookieJwt cookieJwt;
@Autowired private MockMvc mockMvc;
@Test
@WithMockUser
void signIn_givenValidHttpRequest_shouldSucceedWith200() throws Exception {
String stubUsername = "test_04cb017e1fe6";
String stubPassword = "test_567472858b8c";
SignInDto signInDto = new SignInDto();
signInDto.setUsername(stubUsername);
signInDto.setPassword(stubPassword);
when(signService.signIn(signInDto)).thenReturn(1L);
mockMvc
.perform(
post("/auth/sign-in")
.contentType(MediaType.APPLICATION_JSON)
.content(
"""
{
"username": "test_04cb017e1fe6",
"password": "test_567472858b8c"
}
""")
.with(csrf()))
.andExpect(status().isOk());
}
@Test
@WithMockUser
void signIn_givenInValidHttpRequest_shouldFailedWith400() throws Exception {
String stubUsername = "test_04cb017e1fe6";
String stubPassword = "test_567472858b8c";
SignInDto signInDto = new SignInDto();
signInDto.setUsername(stubUsername);
signInDto.setPassword(stubPassword);
when(signService.signIn(signInDto)).thenReturn(1L);
mockMvc
.perform(
post("/auth/sign-in")
.contentType(MediaType.APPLICATION_FORM_URLENCODED)
.content(
"""
{
"username": "test_04cb017e1fe6",
"password": "test_567472858b8c"
}
""")
.with(csrf()))
.andExpect(status().isBadRequest());
when(signService.signIn(signInDto)).thenReturn(1L);
mockMvc
.perform(
post("/auth/sign-in")
.contentType(MediaType.APPLICATION_JSON)
.content(
"""
{
"username": "test_04cb017e1fe6"
}
""")
.with(csrf()))
.andExpect(status().isBadRequest());
}
}
严格来说,上面是一个结合测试
单元测试的框架体系一般分为三种 :
- e2e (接口)测试
- 结合测试
- 方法(单元)测试
上面的案例是一个典型的结合测试。如何区分这些不同的测试呢?答案是按照依赖范围。结合测试一般会依赖某种特定的环境,针对某种特定环境下的代码的业务表现进行测试,SpringMvc 就是一种典型的场景。
仔细想想,如果你采用三层架构来搭建你的项目,还有什么场景也是结合测试的场景?这个答案留给大家思考,也可以本帖中回复一起讨论。
更多单元测试的写法
更多的区分了隔离环境的单元测试代码,都集成到了下面的项目中: