背 景
常规的功能测试,主要关注业务的正常逻辑是否能够走通,往往忽视了各种异常对服务造成影响,因此需要提高异常测试的关注度。异常测试包括很多方面,有服务器系统异常、依赖服务异常、应用本身异常等。
服务器系统异常包括:系统资源CPU、内存不足和机器自身断电宕机引起的异常
依赖服务异常包括:运行过程中数据库,第三方依赖服务无响应,请求其他接口返会异常信息等
应用本身异常包括:应用进程重启、挂掉、假死、响应时间变慢等
日常测试中,异常测试缺失的表现:catch中的代码很少被覆盖。但是随着业务体量的增加,异常代码难免不被触发,如果异常处理不到位,就会引起线上bug,严重还会导致事故发生。
尤其是catch到异常后会进入分支流程的情况。通过接口测试构造抛出catch异常数据是很难做到的,可以通过JVM SandBox 工具注入异常。
JVM SandBox 是一种无侵入,可动态插拔,JVM 层的 AOP 解决方案。只需要通过 JVM SandBox 提供的编程结构告诉“沙箱”,我们希望对哪些类哪些方法进行 AOP,在切面点做什么即可。
JVM SandBox介绍
SandBox设计原理
JVM 沙箱可以被动态地挂载到某个正在运行的目标 JVM 进程之上(前提是目标 JVM 没有禁止 attach 功能),沙箱工作完之后还可以被动态地从目标 JVM 进程卸载掉,沙箱被卸载之后,沙箱对目标 JVM 进程产生的影响会随即消失,沙箱工作示意图如下:
客户端通过 Attach 将沙箱挂载到目标 JVM 进程上,沙箱的启动实际上是依赖 Java Agent,启动之后沙箱会一直维护着 Instrument 对象引用,在沙箱中 Instrument 对象是一个非常重要的角色,它是沙箱访问和操作 JVM 的唯一通道,后续修改字节码和重定义类都要经过 Instrument。另外,沙箱启动之后同时会启动一个内部的 Jetty 服务器,这个服务器用于外部进程和沙箱进行通信。
SandBox使用思想
它的主要思想是将任何一个Java方法的调用都分解为BEFORE、RETURN和THROWS三个环节,并通过这三个环节,实现对入参、返回值和流程进行控制,实现更细粒度的代码层故障注入。
基于BEFORE、RETURN和THROWS三个环节事件,可以完成很多类AOP的操作。其中针对入参、返回值和流程上,可以完成的操作主要有:
可以感知和改变方法调用的入参
可以感知和改变方法调用返回值和抛出的异常
可以改变方法执行的流程。包括在方法体执行之前直接返回自定义结果对象,原有方法代码将不会被执行;在方法体返回之前重新构造新的结果对象,甚至可以改变为抛出异常;在方法体抛出异常之后重新抛出新的异常,甚至可以改变为正常返回
总体实现方案
1、准备模块代码
必要条件 :
实现com.alibaba.jvm.sandbox.api.Module接口
添加注解 @MetaInfServices
必须拥有无参构造函数
方法的传参是Map数据结构,主要传入参数有类名、方法名、异常类型、异常内容。根据这四个参数,可以任意制定在某个方法执行前后抛出什么类型异常以及异常内容。
2、编译打包
XXX-with-dependencies.jar包放/sandbox/module?录
3、获取某个工程进程号
ps -ef | grep serviceName
4、获取端口号和http请求的url地址
修改 sandbox.sh文件在图中的红色框前边加上echo命令保存
执行 sh /opt/soft/sandbox/bin/sandbox.sh -p 24399,输出端口号,以及http方式访问的地址。
5、将模块挂载到JVM中,可以传模块需要的参数
方式一:sh sandbox.sh -p 24399 -d 'moduleName?param=param'
方式二:http请求
http://127.0.0.1:40050/sandbox/default/module/http/module?classPath=com.user.User&methodName=getUserInfo&exceptionName=java.lang.Exception&exceptionContent=拦截异常
以上步骤执行完,将沙箱成功挂载到这个进程上,执行到监听方法时,会执行设置的事件,将异常抛出。比如:catch中的代码无法覆盖到,可以使用该工具,例如addInfo()方法catch部分覆盖不到时,可以设置被调用的方法getUser() 抛出异常。
目前异常测试是有目标的注入异常,让系统可以正确的处理已知问题。异常测试的长期发展在于通过异常注入的手段和系统的改进让系统即使处于不稳定状态下也不会出现雪崩。让系统有更强的环境抗逆性、数据抗逆性、流程抗逆性。以上是异常注入功能初步探索与实现介绍,后续会将注入异常功能平台化,主要侧重于从代码层面构造异常场景,感兴趣的同学可以随时交流。
本文内容不用于商业目的,如涉及知识产权问题,请权利人联系博为峰小编(021-64471599-8017),我们将立即处理