如何在定义Feeders前先执行karate.config读取环境配置
解决Gatling Simulation初始化Feeders前未执行karate.config的问题
问题背景
需要根据环境动态加载配置文件,从中获取用户账号列表作为Gatling测试的Feeders数据源,但执行Simulation类时,karate.config.js未提前执行,导致feeder.feature无法读取到配置值,进而MockUtils无法初始化用户列表,最终报错。
核心原因
- MockUtils中的静态变量在Simulation初始化阶段就会被加载,此时直接调用
Runner.runFeature不会自动触发karate.config.js的执行,缺少配置上下文。 - Gatling的Simulation初始化逻辑早于Karate默认的config加载时机,导致配置未就绪就尝试读取数据源。
解决方案
方案一:手动触发karate.config加载并传递配置上下文
修改MockUtils类,在初始化用户列表前手动执行karate.config.js,确保配置先加载完成:
public class MockUtils { private static final List<String> userAccounts; private static final AtomicInteger counter = new AtomicInteger(); static { // 初始化Karate脚本上下文 ScriptValue initialConfig = ScriptValue.from(new HashMap<>()); ScriptContext context = new ScriptContext(initialConfig, null); // 手动执行karate.config.js加载配置 Karate.executeConfig("classpath:karate.config.js", context); // 获取加载完成的配置对象 Map<String, Object> loadedConfig = context.getConfig().toMap(); // 传入配置执行feeder.feature,获取用户列表 Map<String, Object> featureResult = Runner.runFeature("classpath:com/XXX/feeder.feature", loadedConfig, false).toMap(); userAccounts = (List<String>) featureResult.get("userAccounts"); } public static String getNextUserAccount() { return userAccounts.get(counter.getAndIncrement() % userAccounts.size()); } }
方案二:在Simulation中提前初始化配置与数据源
利用Gatling的beforeAll钩子,在Simulation初始化Feeders前先加载Karate配置并初始化用户列表:
1. 修改MockUtils为懒加载模式
public class MockUtils { private static List<String> userAccounts; private static final AtomicInteger counter = new AtomicInteger(); // 新增初始化方法,传入Karate配置 public static void init(Map<String, Object> karateConfig) { if (userAccounts == null) { Map<String, Object> result = Runner.runFeature("classpath:com/XXX/feeder.feature", karateConfig, false).toMap(); userAccounts = (List<String>) result.get("userAccounts"); } } public static String getNextUserAccount() { return userAccounts.get(counter.getAndIncrement() % userAccounts.size()); } }
2. 修改Simulation.scala,添加beforeAll钩子
import com.intuit.karate.Runner import io.gatling.core.Predef._ import scala.concurrent.duration._ class TestSimulation extends Simulation { // 在所有测试开始前加载Karate配置并初始化数据源 beforeAll { // 加载karate.config,支持通过JVM参数-Denv指定环境 val karateConfig = Runner.config().env(System.getProperty("env", "dev")).toMap() MockUtils.init(karateConfig) } val feeder = Iterator.continually(Map("userAccount" -> MockUtils.getNextUserAccount)) val createScenario = scenario("create").feed(feeder).exec(karateFeature("classpath:XXX/XXX.feature")) setUp( createScenario.inject(rampUsers(2) during (5 seconds)).protocols(protocol) ) }
优化建议
将karate.config.js中的环境配置改为从系统变量读取,方便多环境切换:
var config = { // 优先取JVM参数-Denv,默认dev environment: karate.properties['env'] || 'dev' } config.configJsonFile = karate.readAsString('classpath:com/XXX/config-' + config.environment + '.json')
运行测试时可指定环境:
mvn gatling:test -Denv=test
内容的提问来源于stack exchange,提问作者Anne Chen
相关产品推荐
相关产品推荐

