验证请求状态
之前我们实现了在测试环境中开启Web环境,并且在测试阶段发送虚拟请求,并看到了返回的结果,这次我们不止要看他的请求结果,还要看他的请求过程和请求状态
匹配请求状态
首先就是查看请求的状态。主要介绍的就是一个重要的类,也是我们这一节的核心类:MockMvcResultMatchers,这个类是一个结果匹配器,他会提供不同请求状态的请求对象,然后我们可以拿到本次请求的结果对象与他的请求状态的对象做对比,查看本次请求的状态,具体的代码如下:
操作代码
package com.spring;
import org.junit.jupiter.api.Test;
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.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.RequestBuilder;
import org.springframework.test.web.servlet.ResultActions;
import org.springframework.test.web.servlet.ResultMatcher;
import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
import org.springframework.test.web.servlet.result.StatusResultMatchers;
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT)
@AutoConfigureMockMvc
public class SpringBootTest02ApplicationTests {
@Test
public void test(@Autowired MockMvc mockMvc) throws Exception {
MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.get("/test");
// 获得本次请求的信息
ResultActions perform = mockMvc.perform(builder);
// 获取请求状态信息
StatusResultMatchers status = MockMvcResultMatchers.status();
// 获取请求成功时候的请求状态
ResultMatcher ok = status.isOk();
// 添加对比,将请求成功的状态与本次请求的状态做对比,如果匹配成功则表示请求成功,如果匹配失败,则表示亲请求失败
ResultActions resultActions = perform.andExpect(ok);
System.out.println(resultActions);
}
}
大致的流程就是首先获取本次请求的结果对象,然后获取请求成功时候的对象,两者进行对比,最终的结果就可以反映出请求的结果是否和我们的预期值相同,我们来看运行结果:
如果是请求成功的情况,他本身什么都不会输出,而如果是请求失败了,就会输出很多的信息,我们可以故意把他的请求地址指向一个不存在的地址让他找不到就能看到信息了:
这里改一下他的请求地址,改到一个不存在的地址,这次我们再次运行代码:
这里面的数据就很多了,但是大概的也分为这几个类别,最下面的就是我们这次的匹配结果,很显然,我们设置的预期值是OK,但是他的真实值是not found,很明显的匹配不上,他就告诉我们了。
当然这里面还有一个有意思的地方就是,如果你的预期值就是not found,那么如果你的请求真是没有找到,那么这个程序就不会报错,但是Controller不会被调用,信息也就不会显示出来。哈哈,很无用,谁会故意测试一个Bug呢。
匹配响应体
匹配响应体的过程和匹配相应状态的过程是一样的,只不过是调用的方法替换一下,之前是调用的status()方法,现在改成content()方法,流程都是一样的,设置期待值,与真实值做匹配,最终返回结果:
@Test
public void textBody(@Autowired MockMvc mockMvc) throws Exception {
MockHttpServletRequestBuilder requestBuilder = MockMvcRequestBuilders.get("/test");
ResultActions perform = mockMvc.perform(requestBuilder);
ContentResultMatchers content = MockMvcResultMatchers.content();
ResultMatcher string = content.string("Test Controller ……");
ResultActions resultActions = perform.andExpect(string);
}
我们运行代码测试一下:
如果期待值和真实值是一样的,那么就会一切顺利,如果不一样,就会打印出很多的信息:
之前的信息就不用看了,都是一样的,关键在于后面的信息,预期值和实际值不一样,他会告诉我们请求体是什么,预期的请求体是什么,真实的请求体是什么。
匹配响应体(JSON)
匹配JSON数据和匹配String数据基本是一样的,只不过方法不是String()而是json(),然后预期值的内容也换成json字符串即可。
返回json,最简单的方法就是使用@ResponseBody注解的特性,返回一个对象然后自动将对象转换成json格式在屏幕上显示。
首先我们创建一个类,用于被返回:
这就一切从简了,有两个属性,然后用lombok提供接口方法。然后我们修改一下Controller,让他可以返回对象:
然后我们启动这个SpringBoot,然后访问一下这里看是不是能顺利的打印这个JSON文件:
好,他确实是输出了JSON字符串,剩下的就简单了,换一下方法,然后直接把这个JSON字符串赋值过去当作预期值,然后运行看一下效果:
@Test
public void textBodyJson(@Autowired MockMvc mockMvc) throws Exception {
MockHttpServletRequestBuilder requestBuilder = MockMvcRequestBuilders.get("/test");
ResultActions perform = mockMvc.perform(requestBuilder);
ContentResultMatchers content = MockMvcResultMatchers.content();
ResultMatcher json = content.json("{\"id\":2,\"name\":\"JavaWeb编程\"}");
ResultActions resultActions = perform.andExpect(json);
}
直接复制之后,我们稍微更改一下,让他和真实值有点不同,好让他报错,然后我们看报错信息:
上面的信息就是我们的相应信息,下面的红色的字就是匹配的结果,他会告诉你是哪里的属性出现了问题,这里他就说是id属性,因为我就是修改了id属性,预期值是2,真实值是1 ,匹配不上。
匹配请求头
请求头的匹配流程和之前都是一样的,无非就是方法不一样而已,我们直接上代码:
@Test
public void testHandler(@Autowired MockMvc mockMvc) throws Exception {
MockHttpServletRequestBuilder requestBuilder = MockMvcRequestBuilders.get("/test");
ResultActions perform = mockMvc.perform(requestBuilder);
HeaderResultMatchers header = MockMvcResultMatchers.header();
// 匹配请求头中的键值对,定义规则,当相应的数据不是JSON格式的时候就会匹配不上
ResultMatcher heade = header.string("Content-Type", "application/json");
ResultActions resultActions = perform.andExpect(heade);
预期值是相应的数据类型是JSON格式,也就是说当相应的文件不是JSON格式的时候,就匹配不上就会报错,我们把之前的Controller修改一下:
让他的返回值类型编程String类型,这样在相应的时候就肯定不是JSON格式的了,然后我们启动测试看一下运行结果:
报错了,预期是是JSON类型,实际值是String类型。
可以看到在这种匹配测试的时候其实流程都是差不多的,就是切换一下使用的方法即可。
使用场景
这种匹配测试在使用的时候,一般会多个匹配规则一起使用,比如我们第一个会先匹配响应状态,然后再匹配请求体,最后是请求头,这样我们的规则会更完善,最终的匹配结果也最精准。
大致的代码如下所示
@Test
public void TestMatching(@Autowired MockMvc mockMvc) throws Exception {
MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.get("/tests");
ResultActions perform = mockMvc.perform(builder);
// 首先测试请求状态
StatusResultMatchers status = MockMvcResultMatchers.status();
ResultMatcher ok = status.isNotFound();
perform.andExpect(ok);
// 然后匹配请求体
ContentResultMatchers content = MockMvcResultMatchers.content();
ResultMatcher string = content.string("TestController ……");
perform.andExpect(string);
// 最后匹配响应头
HeaderResultMatchers header = MockMvcResultMatchers.header();
ResultMatcher heade = header.string("Content-Type", "application/json");
perform.andExpect(heade);
}
当然,能测试的部分肯定不止这些,之前我们看到报错信息中:
这里面的内容都可以进行匹配测试,有兴趣的可以自己尝试一下