本文是基于小林coding的文章,主要整理学习了java接口自动化测试的一些知识,知识点主要包括:框架搭建(RestAssured、TestNG、Maven)、与 Python 对比、RestAssured vs HttpClient、数据驱动与鉴权、关联(JsonPath/Context)、Mock(WireMock)、断言(Hamcrest/AssertJ)等
1.创建可运行的最小 Maven + TestNG 项目
1.1 RestAssured+Maven+TestNG的框架相关概念
- Maven:引入 Jar 包,管理项目结构,执行构建命令。①你不需要手动去下载项目所需要的jar包,只需要在
pom.xml文件里写下坐标,Maven 就会自动帮你从网上下载并配置好。②定义了测试的流程(编译、测试、打包)。当你运行mvn test命令时,Maven 会自动触发整个测试流程。 - jar包:其他开发者写好的很多.class代码和配置文件的“压缩包”,不用在意他是怎么实现的,我们直接导入自己的项目中就可以用。
- pox.xml文件:是 Maven 的核心配置文件,记录了项目的基本信息(项目名称,版本号等),依赖列表(告诉maven需要用的jar包)构建配置(用哪个版本的java编译,打包时排除哪些文件)-------总的来说,他记录的是坐标,maven根据这些坐标去互联网上的“中央仓库”自动下载对应的jar包
- RestAssured:构造请求参数,发送 HTTP 请求,解析响应结果。它是专门为 REST API (通过标准的 HTTP 动作(GET, POST, PUT, DELETE)来操作资源,数据格式以JSON 返回)设计的测试库
given()//开始构造一个HTTP请求 .accept(ContentType.JSON)//表明客户端希望服务器返回的格式是JSON格式,相当于在HTTP的请求头header里加Accept: application/json .when()//真正的行为动作 .get("https://httpbin.org/get")//向指定的 URL 发送一个 GET 类型的 HTTP 请求。 .then()//与预期结果对比并进行自动检查 .statusCode(200)//检查服务器返回的状态码是不是 200 .contentType(containsString("application/json"))//确认服务器实际返回的数据类型里确实包含了 application/json 这个字符串 .body("url", equalTo("https://httpbin.org/get"));//检查响应体,JSON 里的 url 字段内容得和我访问的地址一模一样 - TestNG:负责控制测试的运行顺序、逻辑判断、数据驱动以及生成报告。(1.注解:TestNG 会根据这些注解自动运行代码。2.断言:TestNG 提供的
Assert类可以判断实际结果与预期是否相符 3.并行执行 4.数据驱动:同一段逻辑换不同的参数跑 5.测试报告,集成Allure)
@Test:最核心的注解,标记一个方法为“测试用例”。
@BeforeMethod / @AfterMethod:在每个测试方法前后执行(常用于清理缓存)。
@BeforeClass / @AfterClass:在当前类的所有测试方法前后执行一次(常用于初始化数据库连接)。
@BeforeSuite / @AfterSuite:在整套测试方案前后执行(最高层级,常用于启动服务器)。
1.2第一条真实接口测试
用 RestAssured 对外发起一次 HTTP GET 请求,并对状态码、返回类型、关键字段做断言。代码块见上文RestAssured下的代码块。
1.3完成“接口关联”的最小闭环
先调用一个接口 提取响应字段(extract/JsonPath),再把这个字段作为参数传给第二个接口,并断言回显一致。
@Test
public void chainedGetAndAnythingShouldMatchExtractedOrderId() {
String orderId = given()
.accept(ContentType.JSON)
.queryParam("orderId", "A-10086")
.when()
.get("/get")
.then()
.statusCode(200)
.contentType(containsString("application/json"))
.extract()//开始提取操作
.path("args.orderId");//从响应里提取:args.orderId
given()
.accept(ContentType.JSON)
.queryParam("orderId", orderId)
.when()
.get("/anything")
.then()
.statusCode(200)
.contentType(containsString("application/json"))
.body("args.orderId", equalTo(orderId));
}
//.queryParam():往网址(URL)的问号 ? 后面加东西,用来过滤、搜索或传递特定的信息给服务器。
//given().body(...) 我要发给服务器的信息。
//then().body(...) 检查服务器回馈的内容里,某项数据是否正确。
2.java接口自动化与python接口自动化对比
- Python:语法简洁,入门较易,主流框架为Requests+Pytest+Allure,受限于GIL(尽管可以创建多线程,但任何时刻,都只有一个线程在CPU上运行)简洁高效
- JAVA:语法严谨,是强类型语言(代码报错更早,重构更安全),主流框架为RestAssured+TestNG+Allure,它的线程是直接映射到操作系统的原生线程上的(操作系统根据 CPU 的核心数,把各个线程直接分发到不同的核心上去跑。)类型安全,性能好,生态成熟
综上所述,在超大规模接口压测或者复杂数据加密计算时,首选 Java。
3.数据驱动与鉴权
3.1数据驱动(将测试脚本逻辑与数据分离)
@DataProvider:是TestNG的一个注解,把数据不断送入测试方法。其返回值必须是一个二维数组Object[][]或一个迭代器Interator<Object[]> 测试二维数组的每一行代表一次测试执行,每一列代表一个参数。
- 代码内的二维数组,适合逻辑简单的单元测试,或参数非常固定的接口
public class LoginTest {
// 1. 定义数据源
@DataProvider(name = "loginData")//表示提供一批测试数据,名字叫loginData, 供@Test(dataProvider = "loginData")使用
public Object[][] provideData() {
return new Object[][] {
{"user_01", "pass123", true}, // 第一轮:正常登录
{"user_02", "error_pw", false}, // 第二轮:密码错误
{"", "pass123", false} // 第三轮:账号为空
};
}
// 2. 引用数据源
@Test(dataProvider = "loginData")//表示TestNG 会去找名为 loginData 的 DataProvider。然后把DataProvider 的每一行数据,依次喂给这个测试方法。
//TestNG会执行三次testLogin,
public void testLogin(String username, String password, boolean expectedResult) {
System.out.println("执行测试:" + username);
// 这里写 RestAssured 接口请求代码
// Assert.assertEquals(actual, expectedResult);
}
}
- POI 读取 Excel:就是把测试的参数方法(测试用例)写到excel里,Java 通过 Apache POI 库来读取这些数据代码读出来给TestNG
@DataProvider
登录接口demo实现
package com.study;//声明这个包属于com.study包
import org.testng.Assert;//断言
import org.testng.SkipException;//主动跳过测试(例如数据文件缺失时不报失败)
import org.testng.annotations.DataProvider;//定义数据源。
import org.testng.annotations.Test;//声明测试方法。
import java.io.InputStream;//读取资源文件流,这里是Excel文件
/**
* POI + TestNG 数据驱动模板。
* - 读取 src/test/resources/data/login_data.xlsx
* - 表头约定:username | password | expected
* - expected 填 true/false
*/
public class Day05ExcelDataDrivenTemplateTest {
@DataProvider(name = "excelLoginData")//声明一个叫excelLoginData的数据提供器
public Object[][] excelLoginData() throws Exception {
//访问修饰符--返回值类型(二维数组)--方法名--异常处理(在 Java 中,IO 操作是必须进行异常处理的)此处的操作Excel文件属于读写磁盘的IO操作
String resourcePath = "data/login_data.xlsx";//定义资源路径
InputStream inputStream = Thread.currentThread()//获取当前运行代码的线程
.getContextClassLoader()//获取类加载器(ClassLoader)在 Java 中,类加载器负责寻找并加载编译后的 .class 文件和 resources 目录下的资源文件。
.getResourceAsStream(resourcePath);//将文件的相对路径返回到一个输入流上
if (inputStream == null) {
throw new SkipException("跳过:未找到测试数据文件 src/test/resources/" + resourcePath);//报错跳过但可清晰定位
}
return ExcelDataReader.readLoginData(inputStream);
}
@Test(dataProvider = "excelLoginData")//表明该测试的数据源
public void loginByExcelData(String username, String password, boolean expected) {
// 这里先用一个本地模拟逻辑演示断言方式。
// 接入真实接口时,把 actualResult 替换为 API 返回判断即可。
boolean actualResult = simulateLogin(username, password);
Assert.assertEquals(
actualResult,
expected,
String.format("用户名=%s, 密码=%s 的结果与预期不一致", username, password)
);
}
private boolean simulateLogin(String username, String password) {
return !username.isBlank() && "pass123".equals(password);
}
}
3.2鉴权
- JWT/Token:登录后拿到的身份凭证(Token:用户成功登录后,服务端发token,目的是让服务端知道你是谁,有没有权限;JWT是Token的一种实现)
- Bearer 头:把凭证放进请求告诉服务端“我是已登录用户”
- BaseTest 统一注入:把这件事平台化,避免每条用例重复写,提升维护性与稳定性
HTTP 请求头里最常见的鉴权写法:Authorization: Bearer <token>
如果这个头没带、带错、或 token 过期,接口常返回 401 或 403
4.关联
4.1JsonPath(在JSON结构中快速定位和提取数据)
jsonpath是一套标准语法,使我们通过一行简单的表达式,直接定位并提取出你想要的值

4.2传递数据的容器context
context:把上个接口的产出,同步给后续所有需要它的接口。使用方法:
- 定义容器:创建一个能被全局访问的
Map
import java.util.HashMap;
import java.util.Map;
public class TestContext {
// 核心:用一个 Map 存储所有要传递的数据
private static Map<String, Object> innerMap = new HashMap<>();
// 存数据
public static void set(String key, Object value) {
innerMap.put(key, value);
}
// 取数据
public static Object get(String key) {
return innerMap.get(key);
}
// 清空(每个 Test Suite 执行完后建议清空,防止数据污染)
public static void clear() {
innerMap.clear();
}
}
- 提取并存储:在上游接口的响应断言后,利用 JsonPath 提取关键字段并
put进容器。
@Test
public void loginTest() {
Response response = post("/api/login", loginPayload);
// 1. 使用 JsonPath 提取
String token = response.jsonPath().getString("data.token");
// 2. 存入 Context
TestContext.set("session_token", token);
}
- 获取并注入:在下游接口的请求发送前,从容器中
get数据,并注入到 URL、Header 或 Body 中。
@Test
public void createOrderTest() {
// 1. 从 Context 取出数据
String myToken = (String) TestContext.get("session_token");
// 2. 将数据应用到请求中
given()
.header("Authorization", myToken)
.body(orderPayload)
.when()
.post("/api/order")
.then()
.statusCode(200);
}
4.3ThreadLocal
目的:为每个线程提供一份变量的副本,实现线程间的数据隔离。
public class ThreadSafeContext {
// 关键点:使用 ThreadLocal 包裹我们的 Map
private static ThreadLocal<Map<String, Object>> threadContext = ThreadLocal.withInitial(HashMap::new);
// 存数据
public static void set(String key, Object value) {
threadContext.get().put(key, value);
}
// 取数据
public static Object get(String key) {
return threadContext.get().get(key);
}
// 重要:用完必须清理,否则会内存泄漏
public static void remove() {
threadContext.remove();
}
}
5.Mock服务
用可控假服务去代替真实依赖,使自动化测试更稳定
- Stub(桩):我们给 Mock 服务配置的“匹配规则 → 返回结果”。
- 匹配规则:URL、方法、query、header、body(JSONPath/正则)。
- 返回结果:status、headers、body、延迟、断开连接等。
- Record/Playback(录制/回放,可选):把真实请求/响应录下来,后续直接回放(适合快速搭数据,但要注意脱敏)。
- Contract(契约):你用 Mock 固化“接口应该长什么样”,用例就能对结构做断言,避免双方各写各的
3万+

被折叠的 条评论
为什么被折叠?



