
Karate 不支持直接跨 .js 文件导入或调用函数,但可通过内置的 call、callonce 和共享变量机制实现真正解耦、可复用的模块化 API 测试设计。
karate 不支持直接跨 `.js` 文件导入或调用函数,但可通过内置的 `call`、`callonce` 和共享变量机制实现真正解耦、可复用的模块化 api 测试设计。
Karate 是一个面向 API 测试的声明式框架,其核心设计理念是:优先使用 .feature 文件组织逻辑,而非依赖 JavaScript 的模块化机制。虽然 Karate 内置了 JavaScript 引擎(GraalVM),允许在 * def 或 * script 中执行 JS 代码,但它不提供 CommonJS/ESM 模块系统(如 require() 或 import),因此无法像 Node.js 那样直接从一个 .js 文件调用另一个 .js 文件中的函数——这是刻意为之的设计限制,而非缺陷。
✅ 正确的模块化路径如下:
1. 将可复用逻辑封装为独立 .feature 文件
这是 Karate 官方推荐且最健壮的方式。例如,将短信生成逻辑抽象为 features/utils/generate-sms.feature:
Feature: Generate SMS payload
Scenario: generate with payload
* def response = { smsId: 'sms_' + java.lang.System.currentTimeMillis(), status: 'queued' }
* def payload = karate.get('payload') || {}
* def result = karate.call('classpath:features/utils/merge-payload.feature', { base: response, custom: payload })
* def sms = result.merged
* print 'Generated SMS:', sms
* def output = sms然后在主测试中通过 karate.call() 复用:
立即学习“Java免费学习笔记(深入)”;
Feature: End-to-end order flow
Scenario: send order confirmation SMS
* def orderPayload = { orderId: 'ORD-123', mobile: '+8613800138000' }
* def smsResult = karate.call('features/utils/generate-sms.feature', { payload: orderPayload })
* match smsResult.smsId == '#string'? karate.call() 支持传参(对象)、返回值捕获,并自动处理变量作用域隔离,比 JS 函数调用更安全、可调试、可并行。
2. 共享 JS 工具函数:通过 karate.configure('scriptCache', true) + * def 声明
若确需少量通用 JS 工具(如日期格式化、签名计算),可统一定义在 karate-config.js 或单个 .js 文件中,并在每个 .feature 中显式加载:
// src/test/java/karate/utils.js
function generateSmsId() {
return 'sms_' + Date.now();
}
function maskPhone(phone) {
return phone.replace(/(\d{3})\d{4}(\d{4})/, '$1****$2');
}在 .feature 中使用:
* def utils = read('classpath:karate/utils.js')
* def smsId = utils.generateSmsId()
* def masked = utils.maskPhone('+8613812345678')⚠️ 注意事项:
- 所有 JS 文件必须通过 read() 显式加载,无法隐式引用;
- 避免在 JS 中操作 Karate 上下文(如 karate.get('response'))——应在 .feature 层控制数据流;
- 不要试图用 JS 模拟 HTTP 请求(如 fetch),这违背 Karate 设计哲学,且丧失断言、重试、报告等核心能力;
- karate.callonce 可用于全局初始化(如获取 Token),避免重复调用。
总结
Karate 的模块化 = .feature 文件即模块。用 call 组织流程,用 read() 加载纯工具函数,用 def 和 set 管理数据契约。放弃“JS 文件间调用”的思维惯性,转而拥抱 Karate 原生的声明式、可组合、可观测的测试范式,才能真正发挥其在 API 测试领域的工程优势。










