基于Spring Aop 构建 Mock服务
引言
在日常的接口测试中,测试人员常常会遇到以下几种令人头疼的情况:
-
场景一:依赖的接口状态不稳定,导致集成 CI 常常失败,需要耗费大量时间排查非被测目标本身之外的环境问题
-
场景二:做异常测试时构造异常数据成本高、难度大,某些异常数据甚至无法通过正常途径构造
-
场景三:被测目标开发进度先于依赖模块,当测试需要先行介入接口测试,但依赖模块接口尚且不通
面对以上痛点,我们需要做什么?
一、概述
1.1 Mock 定义
Mock 是测试过程中中常见的一种技术,即对于某些不容易构造或者不容易获取的对象,用一个虚拟的对象来创建以便测试的测试方法,从而把测试与测试边界以外的对象隔离开。
引用《淘宝网-接口测试白皮书》中的对 Mock 的定义
在测试当中,mock 是指使用各种技术手段模拟出各种需要的资源以供测试使用。
被 mock 的资源通常有以下特征:
被测目标依赖该资源
该资源可能因为各种原因不稳定、返回结果不断变化或者并不总是能够获取到
该资源跟被测目标本身质量无关
这些资源可能是一个外部或底层接口、一个系统、一组数据对象或者是一整套目标软件 的工作环境等。通过 mock 避免对外部真实资源的依赖实现对被测目标的孤立测试,从而大 大降低测试的难度,节约测试成本。
1.2 Mock 分类
测试中的 Mock 可以大致分为两类:mock 数据和 mock 服务。
-
Mock 数据即 mock 一个对象,写入一些预期的值,通过它进行自己想要的测试。主要适用于单元测试,例如常见的 EasyMock、Mockito 等。
-
Mock 服务即 mock 一个 sever,构造一个依赖的服务并给予他预期的服务返回值,适用范围广,更加适合我们的集成测试。因此我们就 mock server 这种模式进行设计与开发。
二、Spring介绍
2.1 Spring aop概念
AOP
面向切面编程,可以说是OOP(Object Oriented Programming,面向对象编程)的补充和完善。OOP引入封装、继承、多态等概念来建立一种对象层次结构,用于模拟公共行为的一个集合。不过OOP允许开发者定义纵向的关系,但并不适合定义横向的关系,例如日志功能。日志代码往往横向地散布在所有对象层次中,而与它对应的对象的核心功能毫无关系对于其他类型的代码,如安全性、异常处理和透明的持续性也都是如此,这种散布在各处的无关的代码被称为横切(cross cutting),在OOP设计中,它导致了大量代码的重复,而不利于各个模块的重用。
AOP技术恰恰相反,它利用一种称为"横切"的技术,剖解开封装的对象内部,并将那些影响了多个类的公共行为封装到一个可重用模块,并将其命名为"Aspect",即切面。所谓"切面",简单说就是那些与业务无关,却为业务模块所共同调用的逻辑或责任封装起来,便于减少系统的重复代码,降低模块之间的耦合度,并有利于未来的可操作性和可维护性。
使用"横切"技术,AOP把软件系统分为两个部分:核心关注点和横切关注点。业务处理的主要流程是核心关注点,与之关系不大的部分是横切关注点。横切关注点的一个特点是,他们经常发生在核心关注点的多处,而各处基本相似,比如权限认证、日志、事物。AOP的作用在于分离系统中的各种关注点,将核心关注点和横切关注点分离开来。
2.2 Spring Filter过滤器
项目中,我们可以有两种方式进行请求的过滤,一种是Filter过滤器,另一种就是Spring拦截器。它们都是起前置处理器的作用,能够在真正的业务逻辑执行之前进行某些前置处理,例如权限校验、登录校验、日志记录等等。
@Slf4j @Component public class MyFilter implements Filter { @Override public void init(FilterConfig filterConfig) {} @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { filterChain.doFilter(servletRequest, servletResponse); } @Override public void destroy() { } }
2.3 Spring 全局异常处理
使用SpringBoot创建的web项目中,当我们请求的页面不存在(http状态码为404),或者器发生异常(http状态码一般为500)时,SpringBoot就会给我们返回错误信息。
也就是说,在SpringBoot的web项目中,会自动创建一个/error的错误接口,来返回错误信息。Spring 提供了ErrorController接口,重写ErrorController接口自定义异常返回。
@Slf4j @RestController public class MyErrorController implements ErrorController { /** * 默认错误 */ private static final String path_default = "/error"; @Override public String getErrorPath() { return path_default; } /** * JSON格式错误信息 */ @RequestMapping(value = path_default, produces = {MediaType.APPLICATION_JSON_VALUE}) public Object error(HttpServletRequest request, HttpServletResponse response) { return "error"; } }
三、整体方案设计
3.1设计图如下
3.2设计思路
通过Spring Filter拦截请求,获取请求Methond和RequestBody,根据request查询数据库respones,在转发请求到controller中返回该response。
1.存储mock接口:mock服务提供post接口存储接口uri、method、requestBody、responseBody到数据库中。
2.客户端通过API接口发起API请求,其中,所述API请求携带路径信息、附加Methond和Body。
3.Spring Aop 拦截请求,然后根据请求信息查询数据库中responseBody,存储在变量中。
4.在转发请求到controller中返回该response。