How to Pass Multiple Parameters to Groovy’s invokeMethod for Performance Testing
This article explains how to work around Groovy's invokeMethod limitation of accepting only a single Object argument by using String arrays or var‑args, demonstrates Java and Groovy reflection implementations, and provides complete code examples for multi‑parameter performance test scripts.
Background
When extending a distributed performance testing framework, the author needed to invoke methods via Groovy reflection. The groovy.lang.GroovyObject#invokeMethod signature only accepts two parameters: the method name ( String) and a single argument ( Object args). Performance test scripts, however, usually require at least three arguments (thread count/QPS, iteration count/duration, and ramp‑up time), plus optional custom parameters.
Part 1 – Using a String[] as a Single Argument
Test Code
public static void main(String[] args) throws IOException {
ExecuteGroovy.executeMethod("/Users/oker/IdeaProjects/funtester/src/test/groovy/com/funtest/groovytest/perf2.groovy", "test", new String[]{"32", "23"});
}Method Under Test
static void test(String[] a) {
output("FunTester succeeded!${a[0]} ${a[1]}");
}Console Output
INFO-> 当前用户:oker,工作目录:/Users/oker/IdeaProjects/funtester/,系统编码格式:UTF-8,系统Mac OS X版本:10.16
INFO-> FunTester succeeded!32 23
Process finished with exit code 0The test succeeds, proving that a String[] can be passed as the single args parameter.
Part 2 – Passing Multiple Separate Arguments
Test Code
public static void main(String[] args) throws IOException {
ExecuteGroovy.executeMethod("/Users/oker/IdeaProjects/funtester/src/test/groovy/com/funtest/groovytest/perf2.groovy", "test", "32", "23");
}Method Under Test
static void test(String a, String b) {
output("FunTester succeeded!$a $b");
}Console Output
INFO-> 当前用户:oker,工作目录:/Users/oker/IdeaProjects/funtester/,系统编码格式:UTF-8,系统Mac OS X版本:10.16
INFO-> FunTester succeeded!32 23
Process finished with exit code 0This also succeeds, showing that Groovy’s invokeMethod can accept a variable‑length argument list.
Part 3 – Encapsulating the Invocation Logic
Compared with Java reflection, Groovy reflection is much simpler. The author provides two utility methods that hide the low‑level details.
Groovy Helper
public static void executeMethod(String path, String name, Object... args) {
try {
Class<?> groovyClass = loader.parseClass(new File(path));
GroovyObject groovyObject = (GroovyObject) groovyClass.newInstance();
groovyObject.invokeMethod(name, args);
} catch (IOException | ReflectiveOperationException e) {
logger.warn("Failed to get class object {}!", path, e);
fail();
}
}Java Helper (requires explicit type conversion)
public static void executeMethod(String path, Object... paramsTpey) {
int length = paramsTpey.length;
if (length % 2 == 1) FailException.fail("Parameter count error, should be even");
String className = path.substring(0, path.lastIndexOf('.'));
String methodname = path.substring(className.length() + 1);
Class<?> c = null;
Object object = null;
try {
c = Class.forName(className);
object = c.newInstance();
} catch (InstantiationException | IllegalAccessException | ClassNotFoundException e) {
logger.warn("Error creating instance {}", className, e);
}
for (Method method : c.getDeclaredMethods()) {
if (!method.getName().equalsIgnoreCase(methodname)) continue;
try {
Class[] paramTypes = new Class[length / 2];
for (int i = 0; i < paramsTpey.length; i += 2) {
paramTypes[i / 2] = Class.forName(paramsTpey[i].toString());
}
method = c.getMethod(method.getName(), paramTypes);
} catch (NoSuchMethodException | ClassNotFoundException e) {
logger.warn("Method attribute handling error!", e);
}
try {
Object[] actualParams = new Object[length / 2];
for (int i = 1; i < paramsTpey.length; i += 2) {
String typeName = paramsTpey[i - 1].toString();
String valueStr = paramsTpey[i].toString();
Object value = valueStr;
if (typeName.contains("Integer")) {
value = Integer.parseInt(valueStr);
} else if (typeName.contains("JSON")) {
value = JSON.parseObject(valueStr);
}
actualParams[i / 2] = value;
}
method.invoke(object, actualParams);
} catch (IllegalAccessException | InvocationTargetException e) {
logger.warn("Reflection execution failed:{}", path, e);
}
break;
}
}The Java version must convert the incoming String values to the required types because the generic Object... parameters are all strings. Despite this extra step, both implementations are compatible, allowing the same test scripts to run with either language.
Conclusion
By treating multiple parameters as either a String[] or separate var‑args, developers can overcome Groovy’s single‑argument limitation and integrate method invocation seamlessly into performance testing frameworks. The provided utility methods demonstrate clean encapsulation for both Groovy and Java reflection, highlighting Groovy’s simplicity and Java’s need for explicit type handling.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
