前言
单元测试这个东西,仁者见仁智者见智吧,毕竟有程序员即使自己不写单元测试,测试同学还是会有自动化测试之类的东西保证我们代码的健壮性。当然你不写单元测试,用postman,swagger这些东西自己点一点都可以。没办法,公司如果要求你写,那就写吧,我用的是junit+mock ,junit是单元测试的继承,mock是用来模拟http请求的(当然,mock还有其他功能)
1.引入依赖
//spring test 依赖
testCompile group: 'org.springframework.boot', name: 'spring-boot-starter-test', version: '2.3.1.RELEASE'
compile group: 'com.alibaba', name: 'fastjson', version: '1.2.73'
// https://mvnrepository.com/artifact/org.apache.commons/commons-lang3
compile group: 'org.apache.commons', name: 'commons-lang3', version: '3.11'
//引入自己编写的项目模块依赖
compile project(":my-common")
compile 'org.springframework.boot:spring-boot-starter-web:2.3.3.RELEASE'
testCompile group: 'junit', name: 'junit', version: '4.12'
2.编写单元测试
每个单元测试的编写思路:访问接口,用断言判断返回的数据是否满足你的期望
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.my.mybatisplus.user.entity.User;
import com.my.mybatisplus.user.service.IUserService;
import org.apache.commons.lang3.StringUtils;
import org.junit.After;
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.MvcResult;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.result.MockMvcResultHandlers;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
import org.springframework.util.Assert;
import java.util.ArrayList;
import java.util.List;
@RunWith(SpringRunner.class)
@SpringBootTest
@AutoConfigureMockMvc //开启mock
public class UserControllerTest {
@Autowired
private MockMvc mockMvc;
@Autowired
private IUserService userService;
@Before
public void initData() {
List<User> userList = new ArrayList<>();
for (int i = 0; i < 5; ++i) {
User user = new User();
user.setName("这是测试数据" + i);
user.setAge(i);
userList.add(user);
}
userService.saveOrUpdateBatch(userList);
}
@After
public void clearData() {
List<User> userList = new ArrayList<>();
for (int i = 0; i < 5; ++i) {
User user = new User();
user.setName("这是测试数据" + i);
user.setAge(i);
userList.add(user);
}
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.likeRight("name", "这是测试数据");
userService.remove(queryWrapper);
}
/*
* @Description: 增加用户测试
* @Author: KevinLee
* @Date: 2020/12/9 11:16
* @return: void
**/
@Test
public void addTest() throws Exception {
User user = new User();
user.setName("这是测试数据add");
String userJson = JSONObject.toJSONString(user);
//POST 请求
String uri = "/user/user/user";
MvcResult mvcResult = mockMvc.perform(MockMvcRequestBuilders.post(uri).contentType(MediaType.APPLICATION_JSON)
.content(userJson))
.andExpect(MockMvcResultMatchers.status().isOk())
.andDo(MockMvcResultHandlers.print())
.andReturn();
//断言验证正确性
Assert.isTrue(StringUtils.isNotBlank(mvcResult.getResponse().getContentAsString()), "添加用户失败");
User dbUser = JSONObject.parseObject(mvcResult.getResponse().getContentAsString(), User.class);
Assert.isTrue(dbUser.getId() > 0, "添加用户失败");
}
/*
* @Description: 修改用户测试
* @Author: KevinLee
* @Date: 2020/12/9 11:16
* @return: void
**/
@Test
public void updateTest() throws Exception {
QueryWrapper<User> queryWrap = new QueryWrapper<>();
queryWrap.eq("name", "这是测试数据0");
User user = userService.getOne(queryWrap);
user.setName("changed");
String userJson = JSONObject.toJSONString(user);
//POST 请求
String uri = "/user/user/user";
MvcResult mvcResult = mockMvc.perform(MockMvcRequestBuilders.put(uri).contentType(MediaType.APPLICATION_JSON)
.content(userJson))
.andExpect(MockMvcResultMatchers.status().isOk())
.andDo(MockMvcResultHandlers.print())
.andReturn();
//断言验证正确性
Assert.isTrue(StringUtils.isNotBlank(mvcResult.getResponse().getContentAsString()), "更新用户失败");
// User dbUser = JSONObject.parseObject(mvcResult.getResponse().getContentAsString(), User.class);
}
}
3.怎么解决单元测试中需要或者产生的垃圾数据
怎么理解上句话呢?我们可能有下面的场景,现在我们要测试一个更新数据的接口,假设通过id更新数据;由于单元测之间是没有任何关系的,所以你不可能说,当我单独运行更新测试的时候,先点一下插入数据的测试,这样很麻烦,或者说当你更新数据的时候我怎么保证被更新的数据一定存在?另外一个场景是,我们要求单元测试产生的垃圾数据不能保留在数据库中。
解决上面两个场景,用到了@Before @After 来保证操作的数据一定存在,以及数据一定会被清楚