智能 mock 让你在几秒钟内即可获取一个模拟的 API。它通过读取你的接口数据模型,返回看似合理的数据:如格式正确的电子邮件、合理的 timestamp,以及不再是像 xJ8kQ 这样的随机名称。对于大多数前端开发工作而言,这足以解决你的燃眉之急。
接着你遇到了智能 mock 无法处理的场景。例如,你希望 /login 接口在遇到已知用户时返回 200,否则返回 401。你希望 /orders/{id} 接口针对某个特定的 ID 返回“已发货”状态的订单,而针对另一个 ID 返回“已取消”状态的订单。你可能还想根据需要强制返回 500 错误,以便在代码上线到生产环境之前测试错误处理逻辑。由于智能 mock 对每个接口只能返回一种响应结构,无法根据请求进行分支处理。而这正是本指南要帮您解决的问题。
Apifox 通过两个功能来解决这一问题:用于基于规则条件响应的 mock 期望,以及用于处理规则无法表达的复杂逻辑的 mock 脚本。本教程将通过具体的示例向您演示这两者,并解释它们的优先级顺序,以确保您的自定义规则始终能够覆盖智能 mock。如果您还不熟悉基础知识,“API mocking 概览”是一个很好的预热,而 Apifox 是我们全程使用的工具。OpenAPI 规范(OpenAPI Initiative)则定义了使这一切成为可能的设计优先(contract-first)工作流。
什么是条件 mock
条件 mock 实际上就是一条规则:当传入的请求符合 这种特征 时,就返回 对应的响应。Apifox 从两个层面上构建这些规则。
第一层是接口数据模型内部的字段级自定义。你可以将某个字段固定为特定值,也可以附加一个动态的 Faker.js 表达式,使其在每次调用时发生变化。这控制了 字段包含什么内容,但该接口返回的响应结构仍然只有一种。
第二层则是完整的响应 mock 期望。一个期望是一个具有名称的规则,它包含可选的触发条件以及专有的响应 body、状态码和 header。没有设置条件的期望会无条件地返回固定数据。而设置了条件的期望只有在请求匹配条件时才会返回其数据。通过叠加多个期望,你可以实现真正的分支路由:当请求满足条件 A 时返回响应 B,在缺失 header 时返回错误 body,或者针对不同的 path 参数返回不同的 payload。
这第二层使得根据需求模拟错误状态和根据请求生成不同的 body 成为可能。本指南接下来的内容将重点围绕这一层展开。
首先了解字段级动态值
在介绍分支逻辑之前,先了解单个字段是如何获取其值的会有所帮助,因为你的条件响应将复用相同的语法。
在接口的数据模型中,任何字符串字段都可以包含写作 {{$category.method}} 的 Faker.js 表达式。Apifox 会在每次 mock 调用时根据你的 JSON Schema 定义中声明的字段类型重新解析该表达式。
{ "id": "{{$number.int(min=1000,max=9999)}}", "customer": "{{$person.fullName}}", "email": "{{$internet.email}}", "product": "{{$commerce.productName}}", "shippingAddress": "{{$location.streetAddress}}, {{$location.city}}", "orderedAt": "{{$date.between(from='2024-01-01',to='2024-12-31',format='yyyy-MM-dd')}}" }
参数化方法是可行的,因此 {{$number.int(min=1000,max=9999)}} 限制了数值范围,而 {{$date.between(...)}} 则限定了日期范围和格式。您可以在一个字段中拼接静态文本和多个表达式,上面的地址就是通过这种方式构建出来的。如果您需要特定地区的数据,Apifox 支持自定义 mock 语言环境(locales),以便您的姓名、地址和电话号码与特定的语言或国家相匹配。Apifox 中的 Faker.js 参考文档涵盖了完整的方法目录。

这属于智能 mock(Smart mock)的范畴。它是动态的,但不是条件性的。要根据请求进行分支处理,您需要使用 mock 期望。
实战演练:一个返回 200 或 401 的登录接口
经典案例:POST /login 接收包含 username 和 password 的 JSON body。已知用户应获得返回 token 的 200 响应,其他所有用户都应获得 401 响应。
打开正确的标签页
在何处进行配置取决于您的工作模式:
- 在调试模式(Request-first)下,打开该接口并点击 Mock 标签页。

- 在文档模式(Design-first)下,打开该接口并点击 高级 mock 标签页。
两者都会引导至相同的 mock 期望列表。如果您想跟着步骤操作但尚未安装应用程序,可以先下载 Apifox,然后导入或创建一个 /login 接口。
添加成功时的 mock 期望
点击 新建期望。给它起一个 期望名称,例如 login-success。现在添加一个条件。因为 username 存在于 JSON 请求 body 中,所以您可以将其作为 body parameter 进行匹配:在名称字段中填入目标属性的 JSON 路径 username,并将条件设置为等于 alice@example.com。

Body-parameter 条件仅支持 JSON,并且通过名称字段中的 JSON 路径进行匹配,因此嵌套属性使用点路径(例如 user.email)。在 响应数据 中填入成功时的 Payload:
json { "token": "mock-jwt-{{$string.uuid}}", "user": { "id": 4821, "username": "alice@example.com", "role": "member" } }
保存。默认的 HTTP 状态码 是 200,因此对于正常流程,您无需修改任何其他内容。
添加失败时的 mock 期望
再次点击 新建期望。将其命名为 login-failure,并保持其条件为空,以便它作为兜底规则(catch-all)。将其 响应数据 设置为错误 body:
json { "error": "invalid_credentials", "message": "Username or password is incorrect." }
此期望需要一个非默认的状态。打开该期望的 More 标签页,将 HTTP Status Code 设置为 401。顺便提一下,More 标签页也是设置以毫秒为单位的 Response Delay(默认值为 0)以及任何自定义响应 header 的地方。设置 400ms 的延迟是一种非常简便的方法,可以确保你的加载动画(loading spinner)能够真正渲染出来。
顺序至关重要
mock 期望是从上到下依次评估的,第一个匹配的规则生效。因此,login-success 必须位于 login-failure 之上。当请求的 username 等于 alice@example.com 时,会匹配第一条规则并返回 Token。其他任何情况都会落入无条件失败规则,并返回 401。如果你颠倒了顺序,无条件(空白条件)规则将匹配所有内容,而你的成功用例将永远不会被触发。
从接口中复制 mock URL 并测试这两个路径:
# 已知用户 -> 返回 200 及 Token
curl -X POST https://<your-mock-host>/login \
-H "Content-Type: application/json" \
-d '{"username":"alice@example.com","password":"whatever"}'
# 其他任何人 -> 返回 401
curl -X POST https://<your-mock-host>/login \
-H "Content-Type: application/json" \
-d '{"username":"stranger@example.com","password":"whatever"}'
实战演练:根据状态为 /orders/{id} 返回不同的 body
第二个常见案例是根据 path 参数进行分支。你希望 /orders/{id} 针对某一个 ID 返回已发货的订单,而针对另一个 ID 返回已取消的订单,这样你的 UI 就可以在没有真实后端的情况下渲染每种状态。
为每种状态创建一个 mock 期望。为每个期望添加针对 path 参数 id 的条件,然后填写相应的 Response data。
mock 期望 order-shipped,条件:path 参数 id 等于 5001。
{
"id": 5001,
"status": "shipped",
"total": 129.90,
"trackingNumber": "1Z{{$string.alphanumeric(length=16)}}",
"shippedAt": "{{$date.recent(days=3,format='yyyy-MM-dd')}}"
}
mock 期望 order-cancelled,条件:path 参数 id 等于 5002。
{
"id": 5002,
"status": "cancelled",
"total": 0,
"cancelledAt": "{{$date.recent(days=1,format='yyyy-MM-dd')}}",
"refundIssued": true
}
添加最后一个不带任何条件的 mock 期望,返回一个通用的待处理订单,这样任何其他 ID 仍能获得有效的响应,而不是落空。将具体的规则排在兜底规则之上,保存后,你就拥有了一个可以按需渲染各种订单状态的 mock。混合条件同样有效:在 path 条件旁边添加一个 header 条件,两者必须同时满足,因为 Apifox 使用与(AND)逻辑组合多个条件(用文档的话说,就是条件的交集)。
条件并不局限于 body 和 path。你可以匹配 query 参数、header 参数、cookie 参数,甚至 IP 地址,这允许你在测试期间将响应限制在特定的客户端。
按需强制触发错误状态
你不需要一个崩溃的后端来测试异常的响应。一个 mock 期望配合 More 标签页就能为你提供所需的任何状态。
要强制返回 500,可以添加一个 mock 期望,其触发条件由客户端控制,例如 header X-Mock-Scenario 等于 server-error。在 More 标签页中将其 Response data 设置为真实的错误 body,并将 HTTP Status Code 设置为 500。
{
"error": "internal_error",
"requestId": "{{$string.uuid}}",
"message": "Something went wrong on our end. Please retry."
}
现在,同一个接口默认会返回正常的 200,而一旦你发送了该 header,它就会返回 500。你也可以对 404、429(在 More 标签页中设置 Retry-After header)或 503 进行相同的操作。你的前端错误处理终于有内容可以捕获了。如果你在自动化检查中对这些响应进行断言,API 断言指南会与此配置非常契合。
共享项目的一个细节:在 mock 期望列表中,可以针对本地和云端 mock 环境独立开启或关闭每个 mock 期望。因此,你可以在本地保持 500 规则处于激活状态,而在你团队成员访问的云端 mock 中保持关闭。
当规则不够用时:mock 脚本
mock 期望是声明式的。它们进行匹配并返回结果,但无法进行计算。当你需要一个源自请求的字段、计算商品明细的总额,或者需要一个根据多个输入同时改变结构的 body 时,你就需要使用 mock 脚本。
mock 脚本是针对 mock 响应运行的 JavaScript。它位于 Mock 标签页底部的 Mock Script 区域,可以通过开关启用。该脚本暴露了两个全局变量:
$$.mockRequest:通过getParam(key)读取传入的请求,以及headers、cookies、body、formdata和urlencoded。$$.mockResponse:通过setBody()、setCode()、setDelay()、json()以及headers和code属性来构建传出的响应。
以下是一个根据提交的商品明细计算订单总额,并回显调用者货币 header 的脚本:
const body = $$.mockRequest.body;
const items = body.items || [];
const subtotal = items.reduce((sum, item) => {
return sum + item.price * item.quantity;
}, 0);
const currency = $$.mockRequest.headers["x-currency"] || "USD";
$$.mockResponse.setCode(201);
$$.mockResponse.setBody({
orderId: Math.floor(Math.random() * 90000) + 10000,
currency: currency,
subtotal: subtotal,
tax: Number((subtotal * 0.08).toFixed(2)),
total: Number((subtotal * 1.08).toFixed(2))
});
其运行流程是:智能 mock 生成初始响应,你的脚本读取 $$.mockRequest 和当前的 $$.mockResponse,应用其逻辑,调用 $$.mockResponse.setBody()(以及根据需要的 setCode、setDelay 或 headers),最后引擎返回最终结果。如果你想通过数组方法或日期计算来进一步扩展逻辑,MDN JavaScript 参考文档会是一个很好的帮手。
一个容易让人绊倒的规则
Mock 脚本仅适用于 Smart mock。它们不适用于 mock 期望或响应示例。这是最需要牢记的一点:你无法将 mock 脚本与基于期望的响应结合使用。如果某个期望匹配了请求,脚本就绝不会运行。因此,请为每个接口明确选择一种方式。当你想根据固定条件进行分支并返回预设的 body 时,请使用期望。当你需要基于 Smart mock 生成的基础数据生成计算输出时,请使用 mock 脚本。
优先级顺序的解析机制
综合来看,以下是 Apifox 处理任何 mock 请求时的执行顺序:
- 它会自上而下地检查你的期望。第一个所有条件均匹配的期望将生效,并返回其响应。这就是为什么自定义规则优于 Smart mock 的原因:一旦匹配到期望,就会直接中断并跳过其下方的所有内容。
- 如果没有匹配的期望,Apifox 会回退到你在项目设置 - 功能设置 - Mock 设置中设置的 Mock 方式优先级。在这一层级中,Smart mock(以及附加到它的任何 mock 脚本)会生成响应。
心智模型很简单:特定规则优先,生成数据次之。将你的期望按照从最具体到最泛化的顺序排列,如果你想确保必定匹配,可以在最下方保留一个无条件的兜底项,并让 Smart mock 处理其他所有情况。如需深入了解何时使用各层级,API mock 使用场景指南将常见场景与功能进行了对应。
发布前需要注意的易错点
了解以下几点限制可以避免让你陷入混乱的调试中:
- Parameter 条件不支持
{{variables}}。Apifox 项目变量和环境变量在 mock 期望中不可用,因此请在条件中写入字面量值。 - Body-parameter 条件仅支持 JSON,不支持 XML,且必须通过名称字段中的 JSON path 进行匹配。
- 条件中的请求 body 格式必须与接口定义相匹配。对于 form-data 接口,必须使用 form-data 的方式进行 mock,而不能使用 JSON。
- 在 mock 脚本内部,没有日志函数,
pm对象不可用(它与测试脚本的执行环境不同),并且无法使用 Apifox 变量。请保持脚本逻辑的自包含性。
文档中并未指出这些功能受到套餐方案的限制。本地与云端之间唯一的区别仅在于功能上:如前所述,每个环境拥有独立的开关,而不是付费墙。
使用 Apifox CLI 实现工作流自动化
Apifox 中的 mock 功能是一项 GUI 和云端能力。mock 引擎通过本地和云端 mock URL 提供接口服务,并且没有可以直接启动运行中 mock 服务端的 CLI 命令。Apifox CLI 真正增加的是对构建这些 mock 的资源进行控制的能力。
Mock 响应是根据接口数据模型生成的,因此 mock 的准确性取决于接口规范的准确性。CLI 以及驱动它的 AI 编码助手(Cursor、Claude Code、Trae、Codex)可以创建和更新项目中的接口和数据模型。在代码中修改契约并进行同步,即可保持 mock 输出的正确性,无需任何人重新打开应用。
一旦 mock 解决了前端开发的阻塞问题,同一个项目的测试场景就可以在 CI 中以无头(headless)模式运行,从而根据 mock 描述的契约来校验真实的后端:
apifox run -t <scenario_id> -e <env_id> -r cli
这一条命令即可执行您的测试场景并报告结果,从而使 mock 和验证共享同一个单一事实源。Apifox CLI 安装指南介绍了如何进行设置,而 GitHub Actions 中的 Apifox CLI 演练则指导如何将其接入流水线。
FAQ
为什么即使条件看起来正确,我的 mock 期望仍然被忽略了? 几乎总是由于顺序或格式不匹配引起的。Mock 期望是自上而下进行评估的,并且以第一个匹配项为准。因此,位于具体规则之上的宽泛且无条件的规则会直接吞掉该请求。另外,请确认 body 格式与接口规范相匹配(例如 JSON body 对应 JSON path,表单接口对应 form-data 布局)。如果您想重新检查,可以参考 API mock 概览,其中介绍了基础设置。
我可以在同一个响应上同时使用 mock 脚本和 mock 期望吗? 不能。Mock 脚本仅在智能 mock(Smart mock)下运行。它们会被 mock 期望和响应示例忽略。如果某个 mock 期望匹配成功,脚本将永远不会执行。因此,请为每个接口选择一种方法:使用 mock 期望进行基于规则的分支处理,使用脚本进行计算输出。
如何在不破坏默认 200 响应的情况下返回 401 或 500? 添加一个专属的 mock 期望,并设置一个可由客户端控制的条件(使用 header 非常有效),然后打开它的“更多”标签页并设置 HTTP 状态码(HTTP Status Code)。默认响应仍将保持 200;只有在条件匹配时才会触发错误响应。
条件中可以使用我的环境变量吗? 不能。Apifox 的 {{variable}} 变量值在 mock 期望中不可用,并且 parameter 条件也不支持 {{variables}}。请在条件中使用字面量值。
当没有任何 mock 期望匹配时会发生什么? Apifox 将回退到“项目设置 - 功能设置 - Mock 设置”中的“Mock 方式优先级”,此时智能 mock 会根据您的数据模型生成响应。相比之下,添加一个空白条件的兜底 mock 期望是保证特定回退行为的有效方法。
总结
Smart mock 处理常见情况,而 mock 期望则处理所有包含 if 条件的情况:例如已知用户返回 200,否则返回 401;根据不同状态返回不同的订单 body;或者按需返回 500。只有在需要规则无法表达的计算输出时,才需要使用 mock 脚本,并且请记住它仅针对 Smart mock 运行。牢记优先级顺序(特定期望优先,生成的数据次之),您的 mock 将完全像真实的 API 一样进行分支流转。下载 Apifox 以构建您的第一个条件 mock,免费且无需信用卡。
开发必备:API 全流程管理神器 Apifox
介绍完上文的内容,我想额外介绍一个对开发者同样重要的效率工具 —— Apifox。作为一个集 API 文档、调试、设计、测试、Mock、自动化测试于一体的工具,Apifox 是目前提升研发效率的首选。
如果你正在开发项目,不妨试试其极其友好的界面设计,它完全兼容 Postman 和 Swagger 数据格式,导入数据非常方便,,即使是新手也能很快上手,点击这里即可注册使用。

值得一提的是,除了个人和常规团队使用,针对有高安全合规要求、或需要在内网环境协作的企业,Apifox 还提供了深度定制的私有化部署方案。
获取专属报价与部署方案
详细的私有化部署系统架构与安全白皮书
针对您公司规模的专属报价单
免费的 1v1 专属产品演示 (Demo) 机会