Gatling Java跨Simulation文件调用Scenario的权限问题求解
问题背景
原本使用Gatling/Scala,现在转用Gatling/Java,尝试在/assignments/performance/simulations/BaseSimulation.java中调用/assignments/performance/scenarios/LoginScenario/TeacherLoginFlow.java里的LoginFlow场景,但编译报错:
'LoginFlow' is not public in 'com.hmhco.assignments.performance.scenarios.LoginScenario.TeacherLoginFlow'. Cannot be accessed from outside package
错误原因
TeacherLoginFlow里的LoginFlow变量没有添加public修饰符,默认是包访问权限,只能被同一个包内的类访问,而BaseSimulation在不同的包下,所以无法直接访问。
解决方案
步骤1:修改LoginFlow的访问权限
在TeacherLoginFlow类中,给LoginFlow加上public static修饰符(用static可以不用创建类实例直接调用,更适合场景复用):
修改后的TeacherLoginFlow.java核心代码:
package com.hmhco.assignments.performance.scenarios.LoginScenario; import io.gatling.javaapi.core.ScenarioBuilder; import io.gatling.javaapi.http.HttpProtocolBuilder; import io.gatling.javaapi.core.FeederBuilder; import static io.gatling.javaapi.core.CoreDsl.*; import static io.gatling.javaapi.http.HttpDsl.http; import java.util.HashMap; import java.util.Map; public class TeacherLoginFlow { // 建议把常量定义为public static final,方便全局复用 public static final String BASE_URL = "你的基础URL"; public static final int AUTH_FLOW_REPEAT = 1; public static Map<String, String> myMap = new HashMap<>(); public static HttpProtocolBuilder httpProtocol = http .baseUrl(BASE_URL) .shareConnections(); public static FeederBuilder teachers = csv("data/teachers.csv").circular(); // 添加public static修饰符,允许跨包访问 public static ScenarioBuilder loginFlow = scenario("auth-flow").repeat(AUTH_FLOW_REPEAT).on( feed(teachers) .exec(session -> { // 原有业务逻辑代码 return session; }) // 其他exec步骤 ); }
注:Java规范中变量名建议小驼峰格式(
loginFlow而非LoginFlow),可根据习惯调整,但权限修饰符必须添加。
步骤2:修改BaseSimulation的调用逻辑
不需要重复定义feeder,直接复用TeacherLoginFlow里的场景即可,简化代码:
修改后的BaseSimulation.java核心代码:
package com.hmhco.assignments.performance.simulations; import com.hmhco.assignments.performance.scenarios.LoginScenario.TeacherLoginFlow; import io.gatling.javaapi.core.Simulation; import io.gatling.javaapi.core.ScenarioBuilder; import static io.gatling.javaapi.core.CoreDsl.*; public class BaseSimulation extends Simulation { // 定义模拟参数 private static final int NUMBER_OF_USERS = 100; private static final int RAMP_UP = 60; // 单位:秒 private static final int MAX_DURATION = 300; // 单位:秒 // 直接复用TeacherLoginFlow中的场景 private ScenarioBuilder loginTeacherUsers = TeacherLoginFlow.loginFlow; { setUp( loginTeacherUsers.injectOpen(rampUsers(NUMBER_OF_USERS).during(RAMP_UP)) ).maxDuration(MAX_DURATION) // 复用TeacherLoginFlow中定义的http协议配置 .protocols(TeacherLoginFlow.httpProtocol); } }
额外优化建议
如果场景需要动态参数,可以把loginFlow改成静态方法,接收参数后返回ScenarioBuilder,示例:
// 在TeacherLoginFlow中添加静态方法 public static ScenarioBuilder getLoginFlow(int repeatCount) { return scenario("auth-flow").repeat(repeatCount).on( feed(teachers) .exec(session -> { // 业务逻辑代码 return session; }) ); }
在BaseSimulation中调用:
private ScenarioBuilder loginTeacherUsers = TeacherLoginFlow.getLoginFlow(2);
内容的提问来源于stack exchange,提问作者Alexb1999

