2017-09-28 29 views
0

我一直在編寫測試,通過獲取包中的所有@DataProvider方法並運行它們,檢查@DataProvider的失敗(因爲這些測試會被無聲地跳過)。這很好,但是當我嘗試使用@DataProvider(非常元,我知道)實現它時,我遇到了似乎是TestNG中的一個錯誤。以下4個案件中,唯一可行的一個是封裝的一個:如何使用@DataProvider將方法作爲輸入傳遞給@Test?

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中的錯誤嗎?

回答

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的有效組合。

相關問題