前言
在开发中,为了验证代码的可行性,会写测试单元去验证,执行单元测试,就是为了证明这 段代码的行为和我们期望是否一致
接口单元测试
1、Springboot2.4版本以上移除了junit4.x版本依赖,如果需要引入junit4.x版本的,请自行引入,maven仓库地址为: mvnrepository.com/artifact/ju...
2、Springboot高版本默认使用了junit5单元测试
junit5注解说明
注解 | 说明 |
@Test | 表示方法是测试方法,但是与 JUnit4 的 @Test 不同,它的职责非常单一不能声明任何属性,拓展的测试将会由 Jupiter 提供额外测 |
@DisplayName | 为测试类或者测试方法设置展示名称 |
@BeforeAll | 表示在所有单元测试之前执行(被修饰的方法不必须是静态方法) |
@BeforeEach | 表示在每个单元测试之前执行 |
@Timeout | 表示测试方法运行如果超过了指定时间将会返回错误 |
@Disabled | 表示测试类或测试方法不执行 |
@RepeatedTest | 表示方法可重复执行 |
@ExtendWith | 为测试类或测试方法提供扩展类引用 |
@AfterEach | 表示在每个单元测试之后执行 |
@AfterAll | 表示在所有单元测试之后执行(被修饰的方法必须是静态方法) |
单元测试编写
引入以下依赖
xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
MockMvc使用
MockMvc是由spring-test包提供,实现了对Http请求的模拟,其实例化为
typescript
private MockMvc mockMvc;
@Autowired
private WebApplicationContext wac;
@BeforeEach
void setup() {
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build();
}
测试单元编写
(1)先写一个接口
vbnet
public class UserQuery {
private Long id;
private String account;
private String username;
private Long deptId;
private List<Long> roleIds;
private String password;
}
less
@PostMapping
public R<Boolean> save(@RequestBody UserQuery userQuery) {
log.info("保存数据为:{{}}", userQuery);
return R.ok(null, "操作成功");
}
再用测试单元对该接口进行测试
less
import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import cn.com.ut.utsmart.common.core.util.R;
import cn.com.ut.utsmart.light.query.user.UserQuery;
import cn.com.ut.utsmart.light.service.client.UserService;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.nio.charset.StandardCharsets;
import java.util.Collections;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.HttpStatus;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.MvcResult;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;
@SpringBootTest
@DisplayName("UserController测试")
public class LightUserControllerTest {
@MockBean
UserService userService;
@MockBean
private RedisTemplate<String, String> redisTemplate;
// @Autowired
private MockMvc mockMvc;
@Autowired
private ObjectMapper objectMapper;
@Autowired
private WebApplicationContext wac;
@BeforeEach
void setup() {
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build();
}
@Nested
@DisplayName("用户保存单元测试")
public class UserAddTest {
@Test
@DisplayName("请求头合法,Method(POST),ContentType(application/json)) => HTTP_STATUS:200")
public void save_1_test() throws Exception {
UserQuery userQuery = new UserQuery();
userQuery.setUsername("aa");
userQuery.setDeptId(1L);
userQuery.setAccount("aa");
userQuery.setRoleIds(Collections.singletonList(1L));
mockMvc
.perform(post("/light/user").content(objectMapper.writeValueAsString(userQuery))
.contentType("application/json"))
.andExpect(status().isOk());
}
@Test
@DisplayName("请求不合法,Method(Get) => HTTP_STATUS:405")
public void save_2_test() throws Exception {
UserQuery userQuery = new UserQuery();
userQuery.setUsername("aa");
userQuery.setDeptId(1L);
userQuery.setAccount("aa");
userQuery.setRoleIds(Collections.singletonList(1L));
mockMvc
.perform(get("/light/user").content(objectMapper.writeValueAsString(userQuery))
.contentType("application/json"))
.andExpect(status().is(HttpStatus.METHOD_NOT_ALLOWED.value()));
}
@Test
@DisplayName("请求内容不合法,调用service.save()失败 => 返回失败")
public void save_3_test() throws Exception {
UserQuery userQuery = new UserQuery();
userQuery.setUsername("aa");
userQuery.setAccount("aa");
userQuery.setRoleIds(Collections.singletonList(1L));
when(userService.save(userQuery)).thenReturn(false);
// when
MvcResult mvcResult = mockMvc
.perform(post("/light/user").content(objectMapper.writeValueAsString(userQuery))
.contentType("application/json"))
.andExpect(status().isOk())
.andReturn();
// then
String actualRespBody = mvcResult.getResponse().getContentAsString(StandardCharsets.UTF_8);
String expectRespBody = objectMapper.writeValueAsString(R.ok(false, "操作成功"));
assertThat(actualRespBody).isEqualToIgnoringCase(expectRespBody);
verify(userService, times(1)).save(Mockito.any(UserQuery.class));
}
@Test
@DisplayName("请求内容合法,调用service.save()成功 => 返回成功")
public void save_4_test() throws Exception {
UserQuery userQuery = new UserQuery();
userQuery.setUsername("aa");
userQuery.setAccount("aa");
userQuery.setRoleIds(Collections.singletonList(1L));
when(userService.save(userQuery)).thenReturn(true);
// when
MvcResult mvcResult = mockMvc
.perform(post("/light/user").content(objectMapper.writeValueAsString(userQuery))
.contentType("application/json"))
.andExpect(status().isOk())
.andReturn();
// then
String actualRespBody = mvcResult.getResponse().getContentAsString(StandardCharsets.UTF_8);
String expectRespBody = objectMapper.writeValueAsString(R.ok(true, "操作成功"));
assertThat(actualRespBody).isEqualToIgnoringCase(expectRespBody);
verify(userService, times(1)).save(userQuery);
}
@Test
@DisplayName("参数认证不合法,账号为空,Method(POST),ContentType(application/json)) => HTTP_STATUS:400")
public void save_5_test() throws Exception {
UserQuery userQuery = new UserQuery();
userQuery.setUsername("aa");
userQuery.setDeptId(1L);
userQuery.setRoleIds(Collections.singletonList(1L));
MvcResult mvcResult = mockMvc
.perform(post("/light/user").content(objectMapper.writeValueAsString(userQuery))
.contentType("application/json"))
.andExpect(status().is(HttpStatus.BAD_REQUEST.value()))
.andReturn();
String actualRespBody = mvcResult.getResponse().getContentAsString(StandardCharsets.UTF_8);
String expectRespBody = objectMapper.writeValueAsString(R.failed("账号不能为空"));
assertThat(actualRespBody).isEqualToIgnoringCase(expectRespBody);
}
}
}
assertThat使用
assertThat是junit4.4的一个新断言语句,结合 Hamcrest 提供的匹配符,可以用来匹配值是否与期望一致
less
@SpringBootTest
@DisplayName("测试")
public class HelloTest {
@Test
public void hello() {
String data = "aaa";
assertThat(data).isEqualTo("aaa");
}
}
总结
在写方法或者接口过程中,我们可以根据测试用例,写对应的单元测试去测试接口或者方法是否符合预期