使用Karate独立jar运行测试时karate.callSingle引用classpath资源报错求助
问题描述
使用Karate独立Jar运行测试时,karate-config.js中通过karate.callSingle('classpath:auth/oauth2.feature')调用认证脚本会报错找不到资源,但通过Maven运行时该调用正常。已尝试--workdir、--configdir及-cp参数,均未解决。
项目结构
|-src | |-test | | |-resources | | | |-karate-config.js | | | |-tests | | | | |-test1.feature | | | |-auth | | | | |-oauth2.feature | | |-java | | | |-AllTest.java |-pom.xml
关键代码片段
karate-config.js
function fn() { karate.configure('retry', { interval: 0 }); let accessToken = ''; if (karate.env === 'prod') { // 生产环境直接使用模拟token accessToken = 'mock oauth2 access token'; } if (karate.env !== 'prod') { // 独立Jar运行时此处报错:找不到资源 const result = karate.callSingle('classpath:auth/oauth2.feature', {}); accessToken = result.access_token; } return { access_token: accessToken, }; }
auth/oauth2.feature
@ignore Feature: oauth2 Scenario: Obtain oauth2 token * url 'https://example.com' * method get * status 200 # 模拟返回token,实际场景从响应中提取 * def access_token = 'mock oauth2 access token'
tests/test1.feature
Feature: Access token Scenario: Validate access token # 使用配置中获取的token * url 'https://example.com' * method get * status 200 * match access_token == 'mock oauth2 access token'
报错信息
进入src/test/resources目录执行java -jar /tmp/karate.jar .时,报错如下:
org.graalvm.polyglot.PolyglotException: not found: auth/oauth2.feature - com.intuit.karate.resource.ResourceUtils.getResource(ResourceUtils.java:126) - com.intuit.karate.core.ScenarioFileReader.toResource(ScenarioFileReader.java:129) - com.intuit.karate.core.ScenarioFileReader.readFile(ScenarioFileReader.java:64) - com.intuit.karate.core.ScenarioBridge.read(ScenarioBridge.java:731) - com.intuit.karate.core.ScenarioBridge.callSingle(ScenarioBridge.java:229) - <js>.fn(Unnamed:12)
原因分析
Karate独立Jar的classpath:前缀默认指向Jar自身内部的资源,而非当前运行目录下的文件。Maven运行时会自动将src/test/resources加入类路径,所以classpath:能正常找到资源,但独立Jar模式下未默认包含当前目录到类路径中。
解决方法
方法1:使用相对路径(无需classpath前缀)
修改karate-config.js中的调用路径,去掉classpath:前缀,直接使用相对路径:
const result = karate.callSingle('auth/oauth2.feature', {});
这种方式会基于当前运行目录(src/test/resources)查找资源,适合本地直接运行独立Jar的场景。
方法2:通过--classpath参数添加当前目录到类路径
执行命令时,通过--classpath参数将当前目录加入类路径,这样classpath:前缀就能正确识别本地资源:
java -jar /tmp/karate.jar --classpath . .
第一个.表示将当前目录加入类路径,第二个.表示运行当前目录下的所有测试。
方法3:将资源打包到自定义Jar中(适合分发场景)
如果需要将测试资源和Karate打包成一个独立Jar,可以通过Maven的assembly或shade插件将src/test/resources下的资源打包进去,此时classpath:前缀就能正常访问内部资源。
总结
这并非Karate独立Jar的Bug,而是类路径处理逻辑与Maven不同导致的。通过调整路径前缀或显式指定类路径,即可解决资源找不到的问题。
内容的提问来源于stack exchange,提问作者kotoriのねこ

