java-Springboot+Junit-解决如何构建request、response、session、cookie模拟封装http请求问题
环境
- springboot 1.5.6
- jdk 1.8
引言
使用Springboot开发基于Http满足RESTful风格的接口非常方便,完美的支持前后端分离、MVC、微服务等场景。
服务开发的大多数时间都是在调试和测试。随着需求的变化底层逻辑的小变动就可能产生蝴蝶效应,对部分依赖服务功能逻辑有一定影响。
开发时一般都是通过Postman去做mock测试,但是就算是自己写的一些的服务,过了两个月估计连基本的参数都不知道传什么了。
解决此类问题最好的方法就是使用junit做单元测试,在自己写测试通过后,将当时使用的参数和调用以单元测试的形式记录下来,即保留了测试参数又可以在后续逻辑修改后快速的做回归测试。
有些服务需要鉴权或者需要header、cookie等参数时,我们如何写单元测试。
下面介绍一个种构建request对象传递header参数的方法,其它类型的参数大同小异,有了request对象啥都能mock。
构建Request对象
我们知道基于Http的模式,几乎所有参数都包含在Request对象中,要想使用单元测试必须要构建个request对象。
开发时候Request对象一般有两种方法获取。
- 基于spring的自动注入
@PostMapping(value = "/data/buildCeateTableDDL")
@ApiOperation(value = "产品库数据库表创建服务", notes = "")
public void buildCeateTableDDL(@RequestBody String sqlTemplate,HttpServletResponse rsp,HttpServletRequest req) throws Exception {
String html = dataSyncService.ceateTableDDL(sqlTemplate);
rspWrite(rsp, html);
// return ApiResult.ofSuccessResult(msg);
}
- 使用RequestContextHolder对象获取
ServletRequestAttributes servletRequestAttributes =
(ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = servletRequestAttributes.getRequest();
分析了两个代码逻辑后,发现均依赖HttpServletRequest接口。查看实现类时发现MockHttpServletRequest的实现类时springframework提供的。
进这个类看下,发现居然后无惨的构造函数 _ ,随便new下就ok了。
Maven依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
构建基于junit的springboot环境
首先需要让junit运行在springboot环境中,主要的是需要将所有的注入对象生效,否则直接使用@Test去调用基于注解的方法必然报错。
建一个测试基类,需要用到springboot环境时,继承下就可以了。
@RunWith(SpringRunner.class)
//@Transactional
@SpringBootTest(classes = StartApplication.class, webEnvironment = SpringBootTest.WebEnvironment.NONE)
@ActiveProfiles("") //指定环境参数 空=application.yml; local=application-local.yml,
public class TestBase {
/**
* 可以传递header参数
* @param platform
* @param region
*/
public void setRequestHeader(String username,String pwd){
MockHttpServletRequest request = new MockHttpServletRequest();
request.addHeader("username",username);
request.addHeader("pwd",pwd);
RequestContextHolder.setRequestAttributes(new ServletRequestAttributes(request));
}
}
调用依赖header参数的方法
public class xxxxxTest extends TestBase {
@Before
public void init(){
setRequestHeader("admin","123456");
}
@Test
public void testXXXX() throws Exception {
...
Assert.assertTrue(...);
}
}
总结
一看到HttpServletRequest接口有36个实现类时,当时就想自己实现这个接口造个轮子。但看到了接口多达50个需要实现的方法时打消了这个念头。
还是踏实找找有没有已经实习的直接能用的类吧。
去实现HttpServletRequest接口对我们肯定是有帮助的,但是对于完成业务功能来说就有点儿“误入歧途”了,影响了工作效率。
一个Request对象的实现可能需要你去了解一堆的知识点,未知的概念和一个个坑等着你去踩,提高工作效率放到第一位!!!
对于实现HttpServletRequest接口,看似是一种勤奋,其实在掩饰你不爱动脑、不爱思考的一种表现。
不要用肢体的勤劳,掩盖思维的懒惰!!!!