技术分享 | 专项测试技术初识Hook

简介: Hook 技术需要预先分析目标应用的源代码和逻辑,根据目标测试场景设置目标、逻辑和数据,然后运行时动态的对目标函数参数值、逻辑或者返回值做修改,达到修改现有函数逻辑、实现目标测试场景的目的。## Hook的价值在测试中,虽然通过修改数据以实现测试场景的需求,大部分情况下都可以通过 Mock 技术实现,但是还有一小部分场景,例如需要修改应用内部函数的参数、返回值或运行逻辑等情况,这时就需要用
更多技术文章分享和免费资料领取
https://qrcode.ceba.ceshiren.com/link?name=article&project_id=qrcode&from=Aliyun&timestamp=1651045437
Hook 技术需要预先分析目标应用的源代码和逻辑,根据目标测试场景设置目标、逻辑和数据,然后运行时动态的对目标函数参数值、逻辑或者返回值做修改,达到修改现有函数逻辑、实现目标测试场景的目的。

Hook的价值

在测试中,虽然通过修改数据以实现测试场景的需求,大部分情况下都可以通过 Mock 技术实现,但是还有一小部分场景,例如需要修改应用内部函数的参数、返回值或运行逻辑等情况,这时就需要用到 Hook 技术。

单元测试之外,Mock 技术的主要作用是对服务、接口进行 Mock,通过代理等方式将被测服务发送到依赖服务的请求转发给 Mock 服务,再由 Mock 服务根据规则组装预期的返回数据响应给被测服务,达到预期的测试场景。

Hook 技术主要用于服务内部代码逻辑上的修改,当函数间传递的参数或者函数内的逻辑需要进行修改时,数据的传递并没有经过网络,Mock 服务无法对其进行操作,只能通过 Hook 技术通过在运行的代码中插入额外的代码或者在内存中进行操作。这种更精细更底层的修改,相比 Mock 技术能实现更多的修改范围,适用性更广,难度也更大。

JVM Sandbox简介

JVM-Sandbox 是 alibaba 开源的一个 JVM 沙箱容器,只能处理目标为 Java 应用的场景,主要的特点是支持热插拔(可以在目标应用运行中随时进行 Hook 的加载和解除)、可以同时操作挂载多个目标应用,相互之间独立设置互不干扰、支持的目标应用 JDK 版本较广(6-11)。工具本身功能很多,在这里仅介绍和使用它用作 Hook 的部分功能。

JVM Sandbox安装与启动

  • 项目的 github 地址:https://github.com/alibaba/jvm-sandbox
  • 下载所需版本的二进制压缩包,解压(演示所使用的版本为 1.3.3)。
  • 官方声明支持的系统有:Linux/UNIX/MacOS,这几个系统只需要下载解压缩就可以直接运行。
  • 官方并未支持 Windows 系统,所以需要进行如下修改:
  • 安装 Git Bash。
  • 安装 JDK(版本 6-11,演示所用版本为 1.8.0_192),路径中不能带有空格。
  • 在 Shell 脚本中会有 Java 命令的调用,所以电脑中需要,并且因为 Git Bash 运行 Shell 脚本时的目录问题。
  • 修改启动脚本bin/sandbox.sh,将脚本中 183-188 行内容注释。

  • 由于启动脚本中使用了相对路径,所以运行时需要切换到项目的 bin 目录下操作。
  • 在 bin 目录中执行语句./sandbox.sh -p 目标应用pid,当出现如下提示信息,说明 JVM-Sandbox 已经成功启动了。
$ ./sandbox.sh -p 6204
                    NAMESPACE : default
                      VERSION : 1.3.3
                         MODE : ATTACH
                  SERVER_ADDR : 0.0.0.0
                  SERVER_PORT : 4543
               UNSAFE_SUPPORT : ENABLE
                 SANDBOX_HOME : e:/Download/sandbox/bin/..
            SYSTEM_MODULE_LIB : e:/Download/sandbox/bin/..\module
              USER_MODULE_LIB : E:\Download\sandbox\sandbox-module;~/.sandbox-module;
          SYSTEM_PROVIDER_LIB : e:/Download/sandbox/bin/..\provider
           EVENT_POOL_SUPPORT : DISABLE
  • JVM-Sandbox 同时还会对外提供接口,可以通过请求直接操作 JVM-Sandbox,这样就能方便的与自己的测试代码结合使用。

JVM Sandbox示例

  • 目标应用为一段简单的 Java 代码,代码中启动了一个死循环,每次循环会打印report方法接收到的参数值,参数值已经在代码中固定传入,所以运行之后的结果是一串相同的输出内容。具体内容如下:
public class HookTarget {
    final void report(String stringParam, boolean boolParam, int intParam) {
        System.out.println("stringParam is " + stringParam);
        if (boolParam) {
            System.out.println("boolParam is true!");
        } else {
            System.out.println("boolParam is false");
        }
        System.out.println("intParam is " + intParam);
    }

    final void loopReport() throws InterruptedException {
        while (true) {
            report("a", false, 666);
            Thread.sleep(1000);
            System.out.println();
        }
    }

    public static void main(String... args) throws InterruptedException {
        new HookTarget().loopReport();
    }
}
  • 要编写符合 JVM-Sandbox 的 hook 脚本,需要引入sandbox-api和sandbox-debug-module两个依赖。
  • 通过实现 jvm.sandbox 中的 Module 接口,在 AdviceListener 方法中重写 before 方法,这样写入的语句就会在目标方法体执行之前进行执行,能够修改目标方法收到的参数数据。通过advice.changeParameter方法,修改对应位置的参数数值,第一个参数为目标参数的位置,从 0 开始,第二个参数为替换的值。具体代码如下:
import com.alibaba.jvm.sandbox.api.Information;
import com.alibaba.jvm.sandbox.api.Module;
import com.alibaba.jvm.sandbox.api.annotation.Command;
import com.alibaba.jvm.sandbox.api.listener.ext.Advice;
import com.alibaba.jvm.sandbox.api.listener.ext.AdviceListener;
import com.alibaba.jvm.sandbox.api.listener.ext.EventWatchBuilder;
import com.alibaba.jvm.sandbox.api.resource.ModuleEventWatcher;
import org.kohsuke.MetaInfServices;

import javax.annotation.Resource;
import java.util.*;

@MetaInfServices(Module.class)
@Information(id = "ceshiren.com", author = "ceshiren.com")
public class hook_jvm implements Module {

    @Resource
    private ModuleEventWatcher moduleEventWatcher;

    @Command("ceshiren")
    public void ceshiren(final Map<String, String> param) {
        new EventWatchBuilder(moduleEventWatcher)
                .onClass("HookTarget")
                .onBehavior("report")
                .onWatch(new AdviceListener() {
                    @Override
                    protected void before(Advice advice) throws Throwable {
                        advice.changeParameter(0, "Change By Hook!");
                        advice.changeParameter(1, false);
                        advice.changeParameter(2, 965);
                    }
                });
    }
}
  • 项目通过 maven 管理依赖,对应的pom.xml文件内容如下:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.example</groupId>
    <artifactId>ceshiren_book</artifactId>
    <version>1.0-SNAPSHOT</version>
    <dependencies>
        <dependency>
            <groupId>com.alibaba.jvm.sandbox</groupId>
            <artifactId>sandbox-api</artifactId>
            <version>1.3.3</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba.jvm.sandbox</groupId>
            <artifactId>sandbox-debug-module</artifactId>
            <version>1.3.3</version>
            <scope>compile</scope>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-assembly-plugin</artifactId>
                <executions>
                    <execution>
                        <goals>
                            <goal>attached</goal>
                        </goals>
                        <phase>package</phase>
                        <configuration>
                            <descriptorRefs>
                                <descriptorRef>jar-with-dependencies</descriptorRef>
                            </descriptorRefs>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>
  • 脚本编写完毕之后,将项目打成 Jar 包,放到下载的 JVM-Sandbox 项目下 sandbox-module 目录中。

  • 启动写好的 java 目标程序,运行之后命令行开始循环打印之前设置好的语句,内容如下:
stringParam is a
boolParam is false
intParam is 666

stringParam is a
boolParam is false
intParam is 666
  • 在 gitbash 命令行中打开sandbox/bin目录,执行语句./sandbox.sh -p 目标应用进程号 -d 'ceshiren.com/ceshiren',启动 JVM-Sandbox 并对目标程序进行 Hook 操作,变更report方法中传入的参数值,这时再回到目标程序运行的命令行中查看,可以看到命令行中输出的内容已经变更,如下:
stringParam is Change By Hook!
boolParam is false
intParam is 965

stringParam is Change By Hook!
boolParam is false
intParam is 965
  • 输出内容的变更,说明 Hook 已经生效。这样在目标程序运行中修改了方法传入的参数值,达到了 Hook 的目的。
  • 现在执行语句./sandbox.sh -p 目标应用进程号 -S 可以关闭修改,命令行中输出的内容变回了原始的输出内容。

示例简单展示了 JVM-Sandbox 用作 Hook 工具的功能,通过 Hook 功能就可以对 Java 项目的内部运行逻辑和参数、返回值进行修改。测试场景的构建、测试用例的执行都变得更加方便哦~

原文链接

⬇️ 点击“下方链接”,提升测试核心竞争力!+V~ ceshiren001
更多技术文章分享和免费资料领取
https://qrcode.ceba.ceshiren.com/link?name=article&project_id=qrcode&from=Aliyun&timestamp=1651045437
相关文章
|
18天前
|
物联网 测试技术 持续交付
软件测试的艺术与科学:探索自动化测试框架未来技术的融合与创新:探索区块链、物联网和虚拟现实的交汇点
【8月更文挑战第30天】在软件开发的海洋中,测试是确保航行安全不可或缺的灯塔。本文将带领读者揭开软件测试神秘的面纱,深入理解自动化测试框架的重要性和实现方法。通过实际案例,我们将一起探索如何构建高效、可靠的自动化测试系统,从而保障软件质量,提升开发效率。
|
26天前
|
Web App开发 JSON 测试技术
精通Postman接口测试:关联技术与自动化实践指南
这篇文章详细介绍了如何使用Postman进行接口测试,包括关联技术、自动化实践,以及如何通过环境变量和全局变量解决接口之间的关联性问题。
28 0
精通Postman接口测试:关联技术与自动化实践指南
|
1月前
|
存储 安全 测试技术
移动应用的安全测试与加固技术深度解析
【8月更文挑战第2天】随着移动互联网的发展,移动应用成为生活必需,但安全威胁也随之加剧。本文深入探讨移动应用的安全测试与加固技术,包括权限访问、数据加密、安全协议、组件安全测试及渗透测试等内容,同时覆盖源代码、运行时环境、数据传输存储及业务逻辑加固等方面,为开发者提供全面指导,以保护用户数据和企业资产安全。
78 12
|
1月前
|
机器学习/深度学习 人工智能 物联网
探索软件测试的前沿技术与未来趋势
在数字化时代的浪潮中,软件测试作为保障软件质量的重要环节,正经历着前所未有的变革。本文将深入探讨当前软件测试领域的最新技术进展,包括自动化测试、人工智能在测试中的应用、以及云测试平台的发展等。同时,文章也将对软件测试的未来发展趋势进行预测,为读者揭示一个更加智能化、高效化的软件测试新时代。
|
1月前
|
机器学习/深度学习 人工智能 自然语言处理
探索自动化测试的边界:如何有效整合AI技术提升软件质量
随着人工智能技术的飞速发展,其在软件测试领域的应用逐渐深入。本文将探讨自动化测试与AI结合的现状和挑战,分析AI在提升测试效率、发现深层次缺陷等方面的潜力,并提出实现这一融合的实践策略。
31 0
|
1月前
|
机器学习/深度学习 自然语言处理 算法
测试FunAudioLLM在性能、功能、技术先进性等跟国际知名语音大模型进行比较。
测试FunAudioLLM在性能、功能、技术先进性等跟国际知名语音大模型进行比较。
|
2月前
|
机器学习/深度学习 人工智能 算法
探索自动化测试的前沿技术
【7月更文挑战第30天】在软件开发的浪潮中,自动化测试已成为确保产品质量和效率的关键因素。本文将探讨自动化测试的最新进展,包括AI与机器学习的集成、云测试服务的发展,以及持续集成/持续部署(CI/CD)流程中的测试自动化实践。我们将深入分析这些技术如何改变测试策略,提高效率,并预测它们对未来软件测试领域的影响。
26 0
|
5天前
|
移动开发 JSON Java
Jmeter实现WebSocket协议的接口测试方法
WebSocket协议是HTML5的一种新协议,实现了浏览器与服务器之间的全双工通信。通过简单的握手动作,双方可直接传输数据。其优势包括极小的头部开销和服务器推送功能。使用JMeter进行WebSocket接口和性能测试时,需安装特定插件并配置相关参数,如服务器地址、端口号等,还可通过CSV文件实现参数化,以满足不同测试需求。
27 7
Jmeter实现WebSocket协议的接口测试方法
|
5天前
|
JSON 移动开发 监控
快速上手|HTTP 接口功能自动化测试
HTTP接口功能测试对于确保Web应用和H5应用的数据正确性至关重要。这类测试主要针对后台HTTP接口,通过构造不同参数输入值并获取JSON格式的输出结果来进行验证。HTTP协议基于TCP连接,包括请求与响应模式。请求由请求行、消息报头和请求正文组成,响应则包含状态行、消息报头及响应正文。常用的请求方法有GET、POST等,而响应状态码如2xx代表成功。测试过程使用Python语言和pycurl模块调用接口,并通过断言机制比对实际与预期结果,确保功能正确性。
22 3
快速上手|HTTP 接口功能自动化测试
|
5天前
|
JavaScript 前端开发 测试技术
ChatGPT与接口测试
ChatGPT与接口测试,测试通过
16 5