Apifox的Mock脚本功能允许你使用JavaScript深度自定义Mock服务的响应思路,实现从简单数据替换到复杂业务仿真的全方面控制。
Mock脚本的生命周期和执行阶段
每个可编写脚本阶段的具体作用、能访问的变量(API)和常见用途。
Before:请求到达时最先执行,主要用于修改接收到的请求信息。
apifox: 重要对象,用于存取请求值。
apifox.getRequestHeader(): 获取请求头。
apifox.setRequestHeader(): 设置请求头。
apifox.getRequestQuery(): 获取查询参数。
apifox.setRequestQuery(): 设置查询参数。1. 参数重写或补充(如注入测试token),2. 请求头证实和修改 ,3. 请求路由(初步判断)
After:在Apifox一致到本地/云端Mock规则后执行,是生成动态响应内容的重要阶段。
apifox: 重要对象,用于设置响应。
apifox.mockResponse.setStatusCode(): 设置HTTP状态码。
apifox.mockResponse.setHeader(): 设置响应头。
apifox.mockResponse.setBody(): 设置响应体(支持JSON/文本等)。
apifox.getRequestQuery()等: 仍可获取请求信息。1. 根据请求参数动态生成数据,2. 实现分页、搜索等业务思路,3. 生成随机但符合规则的数据(如手机号、身份证),4. 模拟接口成功、失败或异常状态
Tescase (Beta):在After阶段之后执行,主要用于一致并返回特定的测试用例数据。apifox.testcase.系列方法,用于一致和返回预置的用例数据。
1. 针对特定参数返回设定义的复杂或边界值用例数据
2. 实现精确的情形化Mock
代码示例
1. 操作请求信息 (Before 脚本)
在请求被处理前,你可以检查和修改它。
javascript
// 示例:在Before脚本中证实并补充参数
const token = apifox.getRequestHeader('Authorization');
// 情形1: 证实Token
if (!token || !token.startsWith('Bearer ')) {
// 可以提前设置一个错误响应,后续After脚本可以根据此返回
apifox.setVariable('authError', true);
}
// 情形2: 为所有请求添加一个时间戳查询参数
const query = apifox.getRequestQuery();
query.timestamp = new Date().getTime();
apifox.setRequestQuery(query);
// 情形3: 根据请求头进行简单路由标识
const clientType = apifox.getRequestHeader('X-Client-Type');
apifox.setVariable('client', clientType || 'default');
2. 生成动态响应 (After 脚本)
这是最重要的部分,可以根据请求生成千变万化的响应。
javascript
// 示例1:模拟一个带分页的用户列表查询接口
const query = apifox.getRequestQuery();
const page = parseInt(query.page) || 1;
const size = parseInt(query.size) || 10;
const total = 125; // 模拟总数据量
// 生成当前页的模拟数据
const list = [];
for (let i = 0; i < size && (page - 1) * size + i < total; i++) {
const id = (page - 1) * size + i + 1;
list.push({
id: id,
name: `用户${id}`,
// 使用Mock.js语法生成更真实的数据(需保证Apifox环境支持)
email: Mock.mock('@email'),
createTime: Mock.mock('@datetime')
});
}
// 设置响应
apifox.mockResponse.setStatusCode(200);
apifox.mockResponse.setHeader('Content-Type', 'application/json');
apifox.mockResponse.setBody(JSON.stringify({
code: 0,
message: 'success',
data: {
list: list,
page: page,
size: size,
total: total,
hasNext: page * size < total
}
}));
// 示例2:根据请求体参数模拟登录成功/失败
try {
const rawBody = apifox.getRequestBody(); // 获取原始请求体
const body = JSON.parse(rawBody);
const { username, password } = body;
if (username === 'admin' && password === '123456') {
apifox.mockResponse.setBody(JSON.stringify({
code: 0,
message: '登录成功',
data: { userId: 1, token: Mock.mock('@guid'), role: 'admin' }
}));
} else {
apifox.mockResponse.setBody(JSON.stringify({
code: 1001,
message: '用户名或密码错误'
}));
}
} catch (error) {
// 处理请求体分析错误等异常
apifox.mockResponse.setStatusCode(400);
apifox.mockResponse.setBody(JSON.stringify({ error: '无效的请求格式' }));
}
3. 使用内置库和随机数据
Apifox Mock环境一般内置了Mock.js和Lodash等实用库。
javascript
// 假设Mock.js和_ (lodash)可用
// 生成一个逼真的模拟用户列表
const getRandomUserList = (count) => {
return _.times(count, (i) => ({
id: Mock.mock('@id'),
name: Mock.mock('@cname'),
avatar: Mock.mock('@image("100x100")'),
province: Mock.mock('@province'),
city: Mock.mock('@city'),
email: Mock.mock('@email'),
ip: Mock.mock('@ip'),
// 生成随机手机号:1开头,第二位是3-9,后面9位随机
phone: `1${_.random(3,9)}${Mock.mock(/\d{9}/)}`,
lastLogin: Mock.mock('@datetime("yyyy-MM-dd HH:mm:ss")')
}));
};
// 使用函数
const userList = getRandomUserList(10);
apifox.mockResponse.setBody(JSON.stringify(userList));
高级示例
情形一:根据数据库或状态的模拟
模拟需要记忆状态的接口,如领取优惠券、增减库存。
javascript
// 使用Apifox的变量或外部存储模拟状态(注意:变量作用域一般限于单次请求)
// 这是一个概念示例,实际持久化可能需要结合Apifox的“临时变量”或外部服务
let couponInventory = apifox.getVariable('couponInventory') || 100; // 初始库存
const query = apifox.getRequestQuery();
const userId = query.userId;
if (couponInventory > 0) {
couponInventory--;
apifox.setVariable('couponInventory', couponInventory); // 更新变量
apifox.mockResponse.setBody(JSON.stringify({
success: true,
couponCode: Mock.mock('@string("upper", 12)'),
remaining: couponInventory
}));
} else {
apifox.mockResponse.setBody(JSON.stringify({
success: false,
message: '优惠券已领完'
}));
}
情形二:模拟延迟和超时
javascript
// 模拟网络延迟
const delay = apifox.getRequestQuery().delay;
const waitTime = parseInt(delay) || _.random(100, 2000); // 默认随机延迟
// 注意:在真实的Mock脚本环境中,可能不支持同步的sleep,延迟思路可能需要通过脚本执行机制本身或外部配置实现。
// 以下是一个概念示意:
// 实际实现时,可能需要依赖Apifox Mock服务的“延时响应”配置功能,或者使用异步写法。
apifox.mockResponse.setDelay(waitTime); // 假设有这样一个API
// 模拟超时(不返回响应)
const shouldTimeout = apifox.getRequestQuery().timeout === 'true';
if (shouldTimeout) {
// 不调用setBody等方法,或设置一个极长的延迟,以模拟超时
// 具体实现取决于Apifox Mock服务的行为
}
情形三:动态错误注入
javascript
// 根据一定概率或特定参数返回错误
const errorRate = 0.1; // 10%的错误率
const randomValue = Math.random();
if (randomValue < errorRate) {
const errors = [
{ code: 500, message: '服务器内部错误' },
{ code: 503, message: '服务暂时不可用' },
{ code: 429, message: '请求过于频繁' },
{ code: 400, message: `无效参数: ${Mock.mock('@word')}` }
];
const error = errors[_.random(0, errors.length - 1)];
apifox.mockResponse.setStatusCode(error.code);
apifox.mockResponse.setBody(JSON.stringify({ error: error.message }));
return; // 注意提前结束
}
// ... 正常的成功响应思路
调试建议
控制台:在Apifox的Mock脚本编辑器中,使用 console.log() 输出变量值、执行途径。
检查语法:保证JavaScript语法正确,特别是JSON字符串的拼接和处理。
确定变量作用域:理解 apifox.setVariable 和 apifox.getVariable 设置的变量一般在单次请求生命周期内有效。
分步证明:对于复杂脚本,先写一个最小化可工作版本(如直接返回一个固定JSON),再逐步增加思路。
查看日志:在Apifox的Mock服务器日志中查看请求详情和可能的脚本错误信息。