Apifox API 文档、调试、Mock 与测试协作工具手册
Mock 通过,联调为什么仍然崩了
前端按 Apifox Mock 写完列表页,Mock 返回 userName,测试环境的真实响应却是 username。接口文档里字段仍是旧名,后端代码和 OpenAPI 文件各有一次独立修改,自动化场景只断言了状态码。每个工具都显示绿色,但交付仍然失败。
这类故障不是“再发一次请求”能解决的。Apifox 把 API 定义、调试用例、响应示例、Mock 规则和自动化场景放在一个项目里,价值在于让这些对象沿同一份 schema 演进。代价也很明确:团队必须决定谁是 API 主源、哪些数据进入云端、谁有权改变定义,以及 CLI 在 CI 中究竟读取在线数据还是仓库中的导出文件。
当需求只是临时探测一个端点,curl 或 HTTPie 更直接;当测试已经由代码框架维护且 OpenAPI 在仓库中严格审查,也不必为了图形界面再造一份可写定义。Apifox 更适合文档、Mock、调试和场景测试确实需要共同协作的团队。
本地调试先落到桌面客户端
Apifox 提供 Windows、macOS、Linux 桌面客户端和 Web 端。官方 下载页 会列出当前系统与处理器支持,应从这里选择安装包。Web 端受浏览器安全模型限制,不能调用数据库、执行本地代码,GET 和 HEAD 请求也不能携带 Body;本地 Mock 只随桌面客户端运行。因此访问 localhost、内网、企业代理、客户端证书或本地脚本时,桌面客户端更可控。
安装后先在设置中查看客户端版本,不把团队文档写死到某个安装包版本。升级时同时在一台非关键开发机验证请求、脚本、Mock 和场景,再逐步推广。Web 端的本地值保存在浏览器数据中,清理站点数据或更换浏览器配置可能让它消失;桌面端换机也不会自动迁移本地值。
Apifox CLI 基于 Node.js。当前官方安装文档要求 Node.js 不低于 16,团队可以固定为项目开发依赖,减少 CI 漂移。当前 npm 稳定包为 apifox-cli@2.2.7:
npm install --save-dev apifox-cli@2.2.7
npx apifox --version需要全局命令时可按 CLI 安装与运行文档 使用全局安装方式。CI 更适合 npx apifox 和锁文件;这样升级由代码评审触发,而不是取决于 runner 上最后一次全局安装。
先让定义和真实服务说同一种话
用一个可控服务建立证据。新建临时文件 apifox-lab/server.mjs:
import http from "node:http";
const server = http.createServer((request, response) => {
if (request.url === "/health" && request.method === "GET") {
response.writeHead(200, { "content-type": "application/json" });
response.end(JSON.stringify({ status: "ok", version: 1 }));
return;
}
if (request.url === "/users/user-demo" && request.method === "GET") {
response.writeHead(200, { "content-type": "application/json" });
response.end(JSON.stringify({ id: "user-demo", username: "demo" }));
return;
}
response.writeHead(404, { "content-type": "application/json" });
response.end(JSON.stringify({ code: "NOT_FOUND" }));
});
server.listen(7072, "127.0.0.1", () => {
console.log("apifox-lab listening on http://127.0.0.1:7072");
});启动服务:
node apifox-lab/server.mjs在 Apifox 新建实验项目和 local 环境,把 baseUrl 的远程值留空,本地值设为 http://127.0.0.1:7072。创建 GET /health 接口,响应 schema 包含字符串字段 status 和整数 version。在调试页发送 {{baseUrl}}/health,预期得到状态码 200 与 {"status":"ok","version":1}。保存为接口用例,并为状态码、status 和 version 添加断言。
接着创建 GET /users/{id},把响应 schema 故意写成 userName,再请求真实服务。预期状态码仍为 200,但响应校验应指出 schema 中缺少 userName,实际响应出现未定义的 username。这就是反向实验:只断言状态码会放过契约漂移,启用 schema 校验才能把字段差异变成故障证据。修复时应先在唯一主源把字段改为 username,再同步 Mock 示例和场景,不能仅关闭响应校验。
为该接口创建固定 Mock 示例:
{
"id": "user-demo",
"username": "demo"
}分别请求真实环境与本地 Mock。二者都应满足同一 schema;Mock 的作用是验证消费者对契约的使用,不证明后端实现已经正确。再把 Mock 示例改回 userName,预期 Mock 侧的 schema 校验或前端契约测试应失败。这个反例能阻止“Mock 自己绿、实现自己绿”的假一致。
实验结束后停止 Node 进程,删除临时目录、实验项目、本地变量、Mock 和测试报告。云端实验项目不清理会继续占用可见性、定时任务、报告和 owner 的治理空间。
一份 API 定义怎样驱动四种执行对象
Apifox 项目中的接口定义描述 method、path、参数、认证、请求体、响应 schema 和示例。调试用例在定义基础上保存具体输入与断言;Mock 依据 schema、示例或自定义规则生成响应;自动化场景把接口用例与流程控制组合起来。任何一层都允许独立覆盖时,覆盖就必须有 owner 和审查,否则同源只是界面上的邻近关系。
API 主源通常有三种可行模式:
| 主源 | 变更路径 | 主要代价 |
|---|---|---|
| Apifox 项目 | 在分支中改定义,审查后导出 OpenAPI | 云端权限与导出节奏成为关键控制点 |
| 仓库 OpenAPI | 代码评审合并后导入 Apifox | UI 修改必须回写或禁止,导入要防止覆盖 |
| 后端代码生成 | 实现构建时生成 OpenAPI,再同步 Apifox | Mock 和消费者反馈不能直接成为主源变更 |
网关导入适合盘点存量路径,却通常缺少完整业务 schema 和示例,不宜未经审查就成为主源。判断主源是否真的成立,可以做一次字段改名:只有一个入口可以批准改名,其余对象由同步或校验跟进;如果五处都能直接改,团队拥有的是五份真相。
仓库主源可以保留下面的资产:
docs/api/
openapi.yaml
api-tests/apifox/
smoke.export.json
variables.example.jsonopenapi.yaml 进入正常代码评审。导入 Apifox 时先在迭代分支执行,检查删除、重命名、nullable、枚举和鉴权差异,再合并到主分支。Apifox 主源则反向导出 OpenAPI,由 CI 对比仓库基线;发现未审查漂移时阻断,而不是自动覆盖仓库。当前 CLI 可以把项目导出为 OpenAPI,输出必须先落到临时文件再比较,不能直接覆盖已评审基线:
npx apifox export \
--project "<project-id>" \
--format openapi \
--output ./tmp/openapi.from-apifox.json
git diff --no-index -- docs/api/openapi.json tmp/openapi.from-apifox.json差异为零才说明两份定义一致;命令退出非零也可能只是发现差异,流水线要区分“导出失败”和“契约漂移”。导出文件、场景 JSON 和变量文件是三个不同资产,OpenAPI 导出不包含可复现的场景执行链,也不能替代变量与测试数据治理。
远程值、本地值和临时值的优先级
Apifox 的变量可出现在团队全局、项目全局、模块、环境、测试数据和临时作用域。每个持久变量又有远程值和本地值:远程值保存在 Apifox 服务端并同步给团队;本地值只保存在当前设备,设置后优先于远程值,本地值为空时才回退到远程值。这个机制在 变量文档 中有完整优先级说明。
团队可以按下面的方式分层:
baseUrl 的远程值使用可共享测试地址,本地值用于 localhost。假租户、无敏感 feature flag 可以共享远程值。个人 token、账号、密码放本地值,并接受换机后需要重新供应。
被测 API 的 token 来自流水线 Secret,通过 --env-var 或受控变量文件注入;它与访问 Apifox 项目的 Access Token 不是同一个凭证。请求生成的 trace ID 放临时变量,避免写回远程值污染其他人。
一个稳定的反向验证是:把 baseUrl 远程值设为测试环境,本地值设为 http://127.0.0.1:1。桌面端预期连接被拒绝,因为本地值优先;清空本地值后才应访问远程地址。若 CI 使用在线数据但没有上传本地变量文件,它会读取远程值。这解释了“我这能跑、流水线却打到另一个环境”,也说明远程值绝不能保存生产 secret。
Vault Secrets 不是免费的内置共享密码箱。当前它属于商业旗舰版能力,用来从 HashiCorp Vault、Azure Key Vault、AWS Secrets Manager 等外部密钥库获取 secret;获取值加密保存在本地客户端,不与团队成员共享。管理员配置 provider,使用者以自己的 OAuth 或 token 访问。实施前要从 Vault Secrets 文档 检查目标密钥库、许可与权限。
桌面端已取得 Vault 值,不代表 CLI 会自动得到同一值。CLI 运行时需要由流水线注入对应的 APIFOX_VAULT_<KEY> 环境变量;缺少变量时应让场景明确失败,不能回退到远程明文值。环境变量只存在于当前 job,关闭 shell trace,禁止用 echo 验证实际内容,并在隔离 runner 上结束进程后销毁。Vault provider 的元数据可以协作,secret 本身仍由每个执行身份独立授权。
Mock 选择决定数据走到哪里
本地 Mock 随桌面客户端启动,默认只服务本机,适合前端本地联调;Web 端不支持本地 Mock。云端 Mock 由 Apifox 托管,适合团队共享和文档沙箱,但 URL、请求参数与响应数据进入云端边界。Runner Mock 运行在团队自有 Runner,更适合不公开的内网 API 或大规模自动化环境。
Mock 路由依据 method、path、接口 ID、响应示例和期望规则。相同 method + path 的多个接口可能发生匹配冲突;路径不以 / 开头时也不会按普通路径模式进入 Mock。出现“返回了 JSON,但不是我配置的那份”时,应比较最终 Mock URL、method、接口 ID、启用的期望和当前环境,而不是不断修改随机规则。Mock 数据说明 列出了本地、云端和 Runner 的当前路由方式。
云端 Mock 应启用 Token 鉴权,并使用脱敏示例。Token 放 header 比 query 更不容易被代理日志和浏览器历史记录;如果客户端限制只能放参数,也要缩短有效期并限制报告保留。官方明确云端 Mock URL 可能变化且不能用作生产地址,因此消费者配置必须显式标记为测试依赖,不能把它编进生产应用。
Mock 数据需要同时覆盖正常、空集合、字段缺失、业务错误和边界长度。随机智能 Mock 适合探索 UI,却不适合回归断言;回归场景应固定关键示例或自定义期望。任何看起来像真实姓名、手机号、邮箱、订单号或内部域名的数据都要换成合成值。
代理、CA 和客户端证书不是一个开关
Apifox 客户端可以在 设置 -> 网络代理 选择系统代理或自定义代理,配置 HTTP/HTTPS、bypass 和代理认证;Web 端没有这一设置项。修改代理后按界面要求保存并重启。遇到 407 检查代理账号,内网地址被错误转发则配置 bypass,连接超时再检查 DNS、防火墙和代理是否能访问目标网段。网络代理文档 是排查当前入口和字段的依据。
服务端证书由内部 CA 签发时,把 CA 的 PEM 加入证书管理,可以在保持 SSL 验证的情况下建立信任。mTLS 需要按 host 和可选 port 配置 CRT+Key 或 PFX 客户端证书;匹配后 Apifox 在 HTTPS 请求中自动携带,HTTP 请求不会携带。同一域名重复添加时会使用最后添加的证书,轮换应先明确目标证书再删除旧项。CA 和客户端证书说明 给出了格式和 host 匹配规则。
长期关闭 SSL 验证会让中间人、错误网关和证书过期都失去证据。换机、Web 端、CLI 和 Runner 也不能从“项目已同步”推断本地证书已同步;证书和私钥应由设备管理或 CI Secret 单独供应,任务结束后删除临时证书并撤销对应身份。
场景用例进入 CI 的两条路
自动化场景可以组合接口用例、提取变量,并使用 If、For、Wait 等流程控制。一个登录后读取资料的场景,至少应断言登录响应、提取 token、调用受保护接口、校验 schema,并在清理步骤撤销实验会话。只在结尾断言 200 会把前一步的错误数据带到后续请求,最终只留下模糊失败。
Apifox CLI 支持在线数据和导出数据两种运行方式。在线运行按 project、branch、scenario 和 environment ID 读取云端项目,适合希望立即执行最新场景的团队;导出运行读取仓库中的 JSON,适合固定变更、代码评审和可重复构建。二者不能同时充当权威输入。
在线命令应从场景的 CI/CD 面板生成,以避免参数与产品版本脱节,典型形态如下:
npx apifox run \
--access-token "$APIFOX_ACCESS_TOKEN" \
--project "<project-id>" \
--test-scenario "<scenario-id>" \
--branch "<branch-name>" \
--environment "<environment-id>" \
--reporters cli,junit导出运行同样应复制界面生成的命令,并把导出 JSON 固定在仓库。若选择“导出本地值使用”,CLI 还需要 --variables <path> 指向本地变量文件;该文件很可能含 token,必须在 CI 运行时生成并在任务结束后删除,不能提交。场景包含本地数据库连接或外部程序时,还要显式提供 --database-connection 或 --external-program-path,并限制 runner 的网络与文件权限。
CLI 可用 cli、html、json、junit 等 reporter。流水线门禁优先消费 JUnit 和退出码;HTML/JSON 报告可能包含请求头、响应体、断言失败值和测试数据。--upload-report 会把本地报告同步到云端,只有团队已批准该数据流和保留策略时才启用。CLI 命令选项 会随产品更新,流水线升级前应核对参数、登录持久化和报告行为。
Apifox Access Token 继承创建者账号对团队和项目的权限,并不是天然最小权限的服务令牌;它只在创建时显示一次,还可以设置有效期。CI 应使用专门的自动化成员承担 owner,以项目最小角色限制可见范围,设置可接受的最短有效期并建立轮换。--access-token 的值会进入进程参数,因而只应在隔离 runner 上从 masked Secret 注入,关闭 shell trace,禁止在共享主机上用进程列表旁观;job 结束后清理 CLI 登录状态、临时变量文件和报告。在线场景跨项目引用接口时,运行身份需要所有相关项目的访问权限,缺少其中一个项目的权限会让场景无法执行。
用失败形态缩短排查路径
Web 端访问本地接口失败,而桌面端成功,先对照 Web 限制和执行位置;服务端无日志时不要检查业务断言。桌面端出现 ECONNREFUSED,检查本地值覆盖后的最终 host/port、服务监听与防火墙。出现证书错误,按 CA、host、port、证书有效性和客户端证书顺序检查,不先关闭验证。
真实请求成功而 Mock 错误,比较 method、path、接口 ID、当前 Mock 环境和启用的期望。Mock 正确而真实响应校验失败,应把 schema diff 带回主源修复,不能把 Mock 示例当成实现证据。桌面场景通过而 CLI 失败,则检查 CLI 版本、在线/导出模式、branch、environment、远程值、本地变量文件和外部依赖路径。
文档与实现长期漂移时,抽取一次字段变更的完整记录:谁改了主源、何时导入或导出、Mock 与场景怎样更新、CI 是否对 OpenAPI 做 diff。找不到唯一合并点,就先修工作流,再补更多测试。否则自动化只会更快地执行旧定义。
云协作、权限和付费边界一起设计
Apifox SaaS 的项目定义、远程变量、Mock、在线场景、报告和文档发布都在云端协作边界。项目至少有管理员、编辑者、只读成员和禁止访问等内置角色;只读成员仍能查看环境并编辑自己的本地值,编辑者可以修改接口与环境,管理员还能管理项目设置和成员。自定义项目角色属于商业能力,采用前要在 成员角色与权限 和目标团队后台确认。
团队 owner 管成员与项目生命周期,API owner 审接口定义和分支合并,测试 owner 管场景与报告,平台 owner 管 CLI token、Runner 和外部程序,安全 owner 审查公开文档、Mock 与 Vault。主分支保护能减少直接修改,但项目管理员仍可能拥有绕过能力,因此审计不能只依赖按钮禁用。
免费核心能力、商业计划、自定义角色、SSO、Vault、私有化和配额会调整。预算应从 价格页 和目标租户读取当前权益。商业团队通常按团队席位购买,而且游客也可能计入付费席位;多个团队分别计算会让重复成员产生结构性成本。评估时除了席位,还要统计 Runner 资源、云端报告、定时任务、Mock 流量、私有化升级备份和外部密钥库运维。
私有化改变数据存放位置,不会消除账号、权限、证书、备份、升级、审计和 owner 责任。SaaS 不满足数据分级要求时,可以选择 Runner Mock、仓库 OpenAPI 和本地测试链路,或评估私有化;不要为了保留某个界面功能,把生产响应和真实 token 复制到云端示例。
清理、回滚和长期维护
接口定义误导入时,先停止自动同步和文档发布,在迭代分支比较差异,再从主源重新导入或回滚分支。不要立即删除项目,因为删除不可恢复,也会丢失排查所需的变更与 owner 线索。Mock 泄漏时先关闭云端 Mock 或启用鉴权,轮换 Mock Token,再清理示例数据和访问日志中的敏感字段。
CLI 升级要在固定导出数据上比较场景数、步骤数、断言数、退出码和报告字段。在线运行还要验证目标 branch 和 environment 未变化。版本回滚不应复用新版本生成但旧版本无法解释的导出文件;锁文件、导出格式和 runner 镜像要作为一个升级单元。
项目结束时先导出仍需归档的 OpenAPI 与无敏感测试资产,撤销公开文档、云端 Mock、定时任务、访问令牌和 Vault 绑定,转移或删除项目 owner,再清理本地值、数据库配置、证书、代理认证和 CLI 登录信息。CI 中删除 secret、临时变量文件和报告 artifact。长期保留的项目每个季度至少复查成员、管理员、公开链接、远程变量、场景运行量、失败率和无人维护的 Mock。
衡量工具是否仍然值得,不看项目数量,而看协作闭环:一次接口变更是否能在一个主源审查,Mock 和场景是否自动暴露漂移,新成员是否无需共享个人 token 就能复现,CI 是否能从明确输入稳定运行。若团队只使用发送请求功能,却持续支付同步、权限和维护成本,退回仓库原生 OpenAPI 加测试代码可能更合适。
推广前做一次干净环境演练
找一台没有项目缓存和本地值的设备,以只读或最小编辑权限加入项目。先确认缺少 token 时请求明确失败,再注入个人测试 token;远程 baseUrl、本地覆盖和临时变量应表现出可解释的优先级。分别制造错误端口、错误 schema、错误 Mock 期望和缺失跨项目权限,确认能得到连接、契约、Mock 路由和授权四类不同证据。
然后从 CI 运行固定导出场景,再运行在线场景,比较 branch、environment、步骤数和断言数。只有明确选择一种作为正式门禁后,才删除另一条试运行链路。最后检查远程变量、共享历史、公开文档、云端 Mock、报告上传、Token、项目角色和席位,并撤销实验数据。完成这轮演练,Apifox 才真正把定义、调试、Mock 和测试收束成一条可维护的工程链路。
