通过获取包中所有@DataProvider方法的列表并运行它们,我一直在编写检查@DataProviders失败的测试(因为这些测试被静默跳过)。这很好用,但是当我尝试使用@DataProvider(非常Meta,我知道)实现它时,我遇到了似乎是TestNG中的一个错误。在以下4个案例中,唯一有效的案例是封装的案例:
package mypackage;
import org.testng.Assert;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class TestDataProvidersWithMethod {
//////////////// Plain example: Assertion fails
@DataProvider(name = "TestThisDP")
public Object[][] testThisDP() throws IllegalAccessException, InstantiationException, InvocationTargetException, NoSuchMethodException {
Class<?> aclass = this.getClass();
Method method = aclass.getMethod("testThisDP", (Class<?>[]) null);
return new Object[][]{new Object[] {method}};
}
@Test(dataProvider = "TestThisDP")
public void testGiveMethod(Method method) throws IllegalAccessException, InstantiationException, InvocationTargetException {
System.err.println("Method: " + method.getName());
Assert.assertTrue(method.getName().equals("testThisDP")); // FAILS: name is actually "testGiveMethod" for some reason.
}
/////// Encapsulated example, this works, but has extra fluff
class Container{
public Method method;
public Class clazz;
public Container(Method method, Class clazz) {
this.method = method;
this.clazz = clazz;
}
}
@DataProvider(name = "TestThisDP4")
public Object[][] testThisDP4() throws IllegalAccessException, InstantiationException, InvocationTargetException, NoSuchMethodException {
Class<?> aclass = this.getClass();
Method method = aclass.getMethod("testThisDP", (Class<?>[]) null);
return new Object[][]{new Object[] {new Container(method,null)}};
}
@Test(dataProvider = "TestThisDP4")
public void testGiveMethod(Container container) throws IllegalAccessException, InstantiationException, InvocationTargetException {
System.err.println("Method: " + container.method.getName());
Assert.assertTrue(container.method.getName().equals("testThisDP")); // Succeeds!!
}
/////////////////// Weird failure, test isn't run due to TypeMismatch
@DataProvider(name = "TestThisDP2")
public Object[][] testThisDP2() throws IllegalAccessException, InstantiationException, InvocationTargetException, NoSuchMethodException {
Class<?> aclass = this.getClass();
Method method = aclass.getMethod("testThisDP2", (Class<?>[]) null);
return new Object[][]{new Object[] {method ,""}};
}
@Test(dataProvider = "TestThisDP2")
public void testGiveMethod2(Method method, String unused) throws IllegalAccessException, InstantiationException, InvocationTargetException {
System.err.println("Method: " + method.getName());
Assert.assertTrue(method.getName().equals("testThisDP")); // FAILS hard: Type mismatch!!!
}
/////////////////////// Attempt at understanding the failure above..
/////////////////////// This fails like the plain example, from the assertion
@DataProvider(name = "TestThisDP3")
public Object[][] testThisDP3() throws IllegalAccessException, InstantiationException, InvocationTargetException, NoSuchMethodException {
Class<?> aclass = this.getClass();
Method method = aclass.getMethod("testThisDP3", (Class<?>[]) null);
return new Object[][]{new Object[] {"", method }};
}
@Test(dataProvider = "TestThisDP3")
public void testGiveMethod3(String unused, Method method) throws IllegalAccessException, InstantiationException, InvocationTargetException {
System.err.println("Method: " + method.getName());
Assert.assertTrue(method.getName().equals("testThisDP")); // FAILS: name is actually "testGiveMethod" for some reason.
}
}
我做错了什么,或者这是TestNG中的错误?
答案 0 :(得分:2)
这里没有错误。当您基本上Method
作为@Test
方法的参数之一时,TestNG基本上会尝试执行名为Native Injection
的操作。
因此,在您的情况下,TestNG基本上是注入一个代表当前“被调用”Method
方法的@Test
引用。
要停用此Native Injection
,您需要使用注释@NoInjection
。
以下是相同测试代码的固定版本
import org.testng.Assert;
import org.testng.annotations.DataProvider;
import org.testng.annotations.NoInjection;
import org.testng.annotations.Test;
import java.lang.reflect.Method;
public class TestDataProvidersWithMethod {
//////////////// Plain example: Assertion fails
@DataProvider(name = "TestThisDP")
public Object[][] testThisDP() throws Exception {
Class<?> aclass = this.getClass();
Method method = aclass.getMethod("testThisDP", (Class<?>[]) null);
return new Object[][]{new Object[]{method}};
}
@Test(dataProvider = "TestThisDP")
public void testGiveMethod(@NoInjection Method method) {
System.err.println("Method: " + method.getName());
// FAILS: name is actually "testGiveMethod" for some reason.
Assert.assertEquals(method.getName(), "testThisDP");
}
/////// Encapsulated example, this works, but has extra fluff
class Container {
public Method method;
public Class clazz;
Container(Method method, Class clazz) {
this.method = method;
this.clazz = clazz;
}
@Override
public String toString() {
if (clazz == null) {
return method.getName() + "()";
}
return clazz.getName() + "." + method.getName() + "()";
}
}
@DataProvider(name = "TestThisDP4")
public Object[][] testThisDP4() throws Exception {
Class<?> aclass = this.getClass();
Method method = aclass.getMethod("testThisDP", (Class<?>[]) null);
return new Object[][]{new Object[]{new Container(method, null)}};
}
@Test(dataProvider = "TestThisDP4")
public void testGiveMethod(Container container) {
System.err.println("Method: " + container.method.getName());
// Succeeds!!
Assert.assertEquals(container.method.getName(), "testThisDP");
}
/////////////////// Weird failure, test isn't run due to TypeMismatch
@DataProvider(name = "TestThisDP2")
public Object[][] testThisDP2() throws Exception {
Class<?> aclass = this.getClass();
Method method = aclass.getMethod("testThisDP2", (Class<?>[]) null);
return new Object[][]{new Object[]{method, ""}};
}
@Test(dataProvider = "TestThisDP2")
public void testGiveMethod2(@NoInjection Method method, String unused) {
System.err.println("Method: " + method.getName());
// FAILS hard: Type mismatch!!!
Assert.assertEquals(method.getName(), "testThisDP2");
}
/////////////////////// Attempt at understanding the failure above..
/////////////////////// This fails like the plain example, from the assertion
@DataProvider(name = "TestThisDP3")
public Object[][] testThisDP3() throws Exception {
Class<?> aclass = this.getClass();
Method method = aclass.getMethod("testThisDP3", (Class<?>[]) null);
return new Object[][]{new Object[]{"", method}};
}
@Test(dataProvider = "TestThisDP3")
public void testGiveMethod3(String unused, @NoInjection Method method) {
System.err.println("Method: " + method.getName());
// FAILS: name is actually "testGiveMethod" for some reason.
Assert.assertEquals(method.getName(), "testThisDP3");
}
}
对于不涉及@DataProviders
的方案,您可以参考this链接了解Native Injection
的有效组合。