升级TestNG从6.11到6.14.2后工厂方法抛出IllegalArgumentException
我懂你遇到的麻烦了——把TestNG从6.11升级到6.14.2后,原本在@Factory方法里通过参数注入ITestContext的代码直接抛出java.lang.IllegalArgumentException: wrong number of arguments错误,对吧?
问题根源
TestNG在6.12版本之后调整了@Factory方法的参数注入规则:旧版本允许直接把ITestContext作为@Factory方法的参数注入,但新版本里@Factory方法默认只支持注入来自testng.xml的参数(需配合@Parameters注解)或者无参数,直接传ITestContext会被TestNG判定为参数数量不匹配,从而触发错误。
解决办法
这里有两种实用的解决方式,你可以根据自己的代码结构来选:
方法1:通过Reporter工具类获取当前TestContext
利用TestNG自带的Reporter类,在工厂方法里静态获取测试上下文,代码修改如下:
import org.testng.ITestContext; import org.testng.Reporter; import org.testng.annotations.Factory; import org.testng.xml.XmlTest; public class FactoryTest { @Factory public Object[] createInstances() throws Exception { // 通过Reporter获取当前测试结果,进而拿到TestContext ITestContext ctx = Reporter.getCurrentTestResult().getTestContext(); XmlTest currentXmlTest = ctx.getCurrentXmlTest(); String parameterValue = currentXmlTest.getParameter(currentXmlTest.getName()); // 这里继续你的实例创建逻辑,比如返回测试类实例数组 return new Object[]{new YourTestClass(parameterValue)}; } }
注意:如果工厂方法在测试执行早期被调用,
Reporter.getCurrentTestResult()可能返回null,这种情况下建议用方法2。
方法2:在工厂类中通过@BeforeTest注入并缓存TestContext
先在工厂类里用@BeforeTest注解注入ITestContext,保存为成员变量,再在@Factory方法中使用:
import org.testng.ITestContext; import org.testng.annotations.BeforeTest; import org.testng.annotations.Factory; import org.testng.xml.XmlTest; public class FactoryTest { private ITestContext testContext; @BeforeTest public void setTestContext(ITestContext ctx) { this.testContext = ctx; } @Factory public Object[] createInstances() throws Exception { XmlTest currentXmlTest = testContext.getCurrentXmlTest(); String parameterValue = currentXmlTest.getParameter(currentXmlTest.getName()); // 继续你的实例创建逻辑 return new Object[]{new YourTestClass(parameterValue)}; } }
这种方式更稳定,不会出现空指针问题,因为@BeforeTest会在工厂方法执行前完成注入。
补充方案
如果你更倾向于保持@Factory方法接收参数的形式,也可以通过@Parameters注解从testng.xml中直接传递需要的参数,不用直接获取ITestContext:
<!-- testng.xml中配置参数 --> <test name="YourTest"> <parameter name="testParam" value="yourValue"/> <classes> <class name="FactoryTest"/> </classes> </test>
然后修改工厂方法:
@Factory @Parameters("testParam") public Object[] createInstances(String testParam) throws Exception { // 直接使用传递过来的参数 return new Object[]{new YourTestClass(testParam)}; }
内容的提问来源于stack exchange,提问作者pavanraju

