3、web环境请求结果比对
目前已经成功的发送了请求,但是还没有起到测试的效果,测试过程必须出现预计值与真实值的比对结果才能确认测试结果是否通过,虚拟请求中能对哪些请求结果进行比对呢?其实发完请求得到的信息只有一种,就是响应对象。至于响应对象中包含什么,就可以比对什么。常见的比对内容如下:
响应状态匹配
@Test void test02(@Autowired MockMvc mvc) throws Exception { MockHttpServletRequestBuilder requestBuilder = MockMvcRequestBuilders.get("/books"); ResultActions actions = mvc.perform(requestBuilder); //设定预期值,与真实值进行比较,成功测试通过,失败测试失败 //定义本次调用的预期值 StatusResultMatchers status = MockMvcResultMatchers.status(); //预计本次调用时成功:状态200 ResultMatcher ok = status.isOk(); //添加预计值到本次调用过程中进行匹配 actions.andExpect(ok); }
正确结果:
假如我们把地址改为/bookss,就会报错:
响应体匹配(非json数据格式)
@Test void test03(@Autowired MockMvc mvc) throws Exception { MockHttpServletRequestBuilder requestBuilder = MockMvcRequestBuilders.get("/books"); ResultActions actions = mvc.perform(requestBuilder); ContentResultMatchers content = MockMvcResultMatchers.content(); ResultMatcher result = content.string("Hello~~"); actions.andExpect(result); }
我们再写一个controller用于测试新的内容,代码如下图:
响应体匹配(json数据格式,开发中的主流使用方式)
@Test void test04(@Autowired MockMvc mvc) throws Exception { MockHttpServletRequestBuilder requestBuilder = MockMvcRequestBuilders.get("/books/getJson"); ResultActions actions = mvc.perform(requestBuilder); ContentResultMatchers content = MockMvcResultMatchers.content(); ResultMatcher result = content.json("{\"name\":\"cabbage\",\"age\":21,\"email\":\"cabbage@qq.com\"}"); actions.andExpect(result); } }
响应头信息匹配
@Test void test05(@Autowired MockMvc mvc) throws Exception { MockHttpServletRequestBuilder requestBuilder = MockMvcRequestBuilders.get("/books/getJson"); ResultActions actions = mvc.perform(requestBuilder); HeaderResultMatchers header = MockMvcResultMatchers.header(); ResultMatcher contentType = header.string("Content-Type", "application/json"); actions.andExpect(contentType); } }
基本上齐了,头信息,正文信息,状态信息都有了,就可以组合出一个完美的响应结果比对结果了。以下范例就是三种信息同时进行匹配校验,也是一个完整的信息匹配过程。
@Test void testGetById(@Autowired MockMvc mvc) throws Exception { MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.get("/books/getJson"); ResultActions action = mvc.perform(builder); StatusResultMatchers status = MockMvcResultMatchers.status(); ResultMatcher ok = status.isOk(); action.andExpect(ok); HeaderResultMatchers header = MockMvcResultMatchers.header(); ResultMatcher contentType = header.string("Content-Type", "application/json"); action.andExpect(contentType); ContentResultMatchers content = MockMvcResultMatchers.content(); ResultMatcher result = content.json("{\"name\":\"cabbage\",\"age\":21,\"email\":\"cabbage@qq.com\"}"); action.andExpect(result); }
总结:
web虚拟调用可以对本地虚拟请求的返回响应信息进行比对,分为响应头信息比对、响应体信息比对、响应状态信息比对
五、数据层测试回滚
测试用例如果测试时产生了事务提交就会在测试过程中对数据库数据产生影响,进而产生垃圾数据。这个过程不是我们希望发生的,作为开发者测试用例该运行运行,但是过程中产生的数据不要在我的系统中留痕,这样该如何处理呢?
我们只需要在原始测试用例中添加注解@Transactional即可实现当前测试用例的事务不提交。当程序运行后,只要注解@Transactional出现的位置存在注解@SpringBootTest,springboot就会认为这是一个测试程序,无需提交事务,所以也就可以避免事务的提交。
我们先创建一个新的表,表里面没有任何数据,如图:
创建对应的实体类,配置好数据库连接的环境,这些就不仔细介绍了,不会的小伙伴们,可以去我的专栏中查找~
开始测试:
@SpringBootTest @Transactional @Rollback(false) public class SqlTest { @Autowired private UserMapper userMapper; @Test void test01() { User user = new User(); user.setName("cabbage"); user.setAge(20); user.setEmail("cabbage@qq.com"); userMapper.insert(user); } }
上述代码运行后并不会对数据库产生影响,但是如果把false改为true,再次执行代码,数据库就会出现垃圾数据,如图所示:
如果我们想提交事物,只需要添加一个@RollBack的注解,设置回滚状态为false即可正常提交事务,是不是很方便呢?springboot在辅助开发者日常工作这一块展现出了惊人的能力,实在太贴心了。
总结:
在springboot的测试类中通过添加注解@Transactional来阻止测试用例提交事务
通过注解@Rollback控制springboot测试类执行结果是否提交事务,需要配合注解@Transactional使用
六、测试用例数据设定
对于测试用例的数据固定书写肯定是不合理的,springboot提供了在配置中使用随机值的机制,确保每次运行程序加载的数据都是随机的。具体如下:
testcase: book: id: ${random.int} id2: ${random.int(10)} type: ${random.int!5,10!} name: ${random.value} uuid: ${random.uuid} publishTime: ${random.long}
当前配置就可以在每次运行程序时创建一组随机数据,避免每次运行时数据都是固定值的尴尬现象发生,有助于测试功能的进行。数据的加载按照之前加载数据的形式,使用@ConfigurationProperties注解即可
@Component @Data @ConfigurationProperties(prefix = "testcase.book") public class BookCase { private int id; private int id2; private int type; private String name; private String uuid; private long publishTime; }
让我们写个代码测试一下:
@SpringBootTest public class RandomTest { @Autowired private BookCase bookCase; @Test void test01() { System.out.println(bookCase.getId()); System.out.println(bookCase.getName()); } }
运行结果:
对于随机值的产生,还有一些小的限定规则,比如产生的数值性数据可以设置范围等,具体如下:
${random.int}表示随机整数
${random.int(10)}表示10以内的随机数
${random.int(10,20)}表示10到20的随机数
其中()可以是任意字符,例如[],!!均可
七、总结
这一篇总结了常用的代码测试的方法,去大厂真的是必不可少!希望小伙伴们都可以认真掌握,创作不易,喜欢的话,可以给博主三连支持哦~~