当前位置: 首页 > 测试知识 > Apifox Mock脚本进阶:使用JavaScript自定义响应逻辑
Apifox Mock脚本进阶:使用JavaScript自定义响应逻辑
2025-12-31 作者cwb 浏览次数394

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服务器日志中查看请求详情和可能的脚本错误信息。


文章标签: 软件测试 测试工具
咨询软件测试