【问题标题】:Why is the constructor not taking a value passed during object creation?为什么构造函数在对象创建期间不接受传递的值?
【发布时间】:2021-12-16 05:44:03
【问题描述】:

我正在编写一个代码,其中我正在使用具有三张工作表的 excel 文件进行操作。我正在将 Apache POI 和数据提供者注释用于数据驱动方法。我想在运行时传递工作表索引号或工作表名称,但我无法将参数设置为数据提供程序方法。所以我所做的是我写了一个构造函数和一个静态变量作为整数。在参数化构造函数中,我初始化了该静态变量,然后在我的测试用例中,通过创建具有数据提供者方法的类的对象,我传递了一个整数,即我希望从中获取数据以运行测试的工作表索引.但是每次,构造函数都将值设为0。我不知道为什么。下面是我写的数据驱动代码和构造函数。

public class Excel_Util {
    static int fileinitial;
    public Excel_Util(int filename) {
        fileinitial=filename;
    }
    @DataProvider(name="testdata")
    public static Object[][] readexcelretobj() throws Exception {
        
FileInputStream f= new FileInputStream("F:\\Eclipse Java new Programs\\shdtestpeopleinteractive\\src\\test\\resources\\Test_data.xls");
        
HSSFWorkbook workbook = new HSSFWorkbook(f);
HSSFSheet s = workbook.getSheetAt(fileinitial);
HSSFRow row = s.getRow(0);
int rownum=s.getPhysicalNumberOfRows();
int colnum=row.getLastCellNum();

//System.out.println(rownum);
//System.out.println(colnum);
Object data[][] = new Object[rownum][colnum];
List<Object> l = new ArrayList<Object>();
for(int i=0;i<rownum-1;i++) {
    row = s.getRow(i+1);
    for(int j=0;j<colnum;j++) {
        HSSFCell c  = row.getCell(j);
        //l.add(c.getStringCellValue());
        data[i][j]=c.getStringCellValue();
    }
}

return data;
        }
    

我写的测试用例如下。

@Test(dataProvider="testdata",dataProviderClass=Excel_Util.class)
    public void testsignupdatafields(String email, String password) {
        Syncutil.Implicitwait();
        try {
            Excel_Util ex = new Excel_Util(2);
            getdriver().get("https://www."+csvreaderutil.csvread().get(0).toString()+"/");
            Marathishd marathishdpage = PageFactory.initElements(getdriver(), Marathishd.class);
            Signuppagemarathishd signup = marathishdpage.letsbeginclick();
            signup.emailid.sendKeys(email);
            signup.password.sendKeys(password);


        }catch(Exception e) {System.out.println("Exception");}
    }
}

在这里,我在创建对象时传递了 2,但每次都从第一张表中获取值。即,每次都考虑工作表索引 0。我不想在 excelutil 类代码中硬编码任何值,因为我想将其作为通用代码。所以在测试用例本身我决定通过表号。我很困惑该怎么做,想知道为什么会发生这种情况以及我正在做的错误是什么。有人可以指导我吗?

【问题讨论】:

    标签: java selenium testng


    【解决方案1】:

    我简化了代码以复制问题。

    现有代码:

    @Test方法

    @Test(dataProvider = "testdata", dataProviderClass = Excel_Util.class)
    public void testsignupdatafields(String email, String password) {
        System.out.println("Test started");
        new Excel_Util(2);
        System.out.println("Email: " + email + " & Passowrd: " + password);
    
    }
    

    Excel_Util

    public class Excel_Util {
    static int fileinitial;
    
    public Excel_Util(int filename) {
        fileinitial = filename;
        System.out.println("Constructor called...");
        System.out.println("Sheet number: " + fileinitial);
    }
    
    @DataProvider(name = "testdata")
    public static Object[][] readexcelretobj() throws Exception {
        Object[][] object = new Object[1][2];
        object[0][0] = "Nandan";
        object[0][1] = "123456";
        System.out.println("Data provider called...");
        System.out.println("Sheet number: " + fileinitial);
        return object;
     }
    }
    

    输出

    Data provider called...
    Sheet number: 0
    Test started
    Constructor called...
    Sheet number: 2
    Email: Nandan & Passowrd: 123456
    

    如果您看到上面的输出,则首先调用 DataProvider 代码,因此您的值将作为 0 传递。要解决此问题,请将new Excel_Util(2); 对象调用为DataProvider

    更新代码:

    @Test 方法

    @Test(dataProvider = "testdata", dataProviderClass = Excel_Util.class)
    public void testsignupdatafields(String email, String password) {
        System.out.println("Test started");
        System.out.println("Email: " + email + " & Passowrd: " + password);
    
    }
    

    Excel_Util

    public class Excel_Util {
    static int fileinitial;
    
    public Excel_Util(int filename) {
        fileinitial = filename;
        System.out.println("Constructor called...");
        System.out.println("Sheet number: " + fileinitial);
    }
    
    @DataProvider(name = "testdata")
    public static Object[][] readexcelretobj() throws Exception {
        new Excel_Util(2);
        Object[][] object = new Object[1][2];
        object[0][0] = "Nandan";
        object[0][1] = "123456";
        System.out.println("Data provider called...");
        System.out.println("Sheet number: " + fileinitial);
        return object;
     }
    }
    

    输出

    Constructor called...
    Sheet number: 2
    Data provider called...
    Sheet number: 2
    Test started
    Email: Nandan & Passowrd: 123456
    

    如果您现在看到上面的输出,则首先调用构造函数。

    解决方案#1:

    正如我们所讨论的,如果你想从 Test 类传递值,那么你可以做这样的事情。而不是 constructor 使用 static 块。

    Test

    public class ClassTestNG {
    static int sheetNumber = 2;
    @Test(dataProvider = "testdata", dataProviderClass = Excel_Util.class)
    public void testsignupdatafields(String email, String password) {
        System.out.println("Test started");
        System.out.println("Email: " + email + " & Passowrd: " + password);
    }
    

    Excel_Util

    public class Excel_Util {
    static int fileinitial;
    static {
        fileinitial = ClassTestNG.sheetNumber;
        System.out.println("Static called...");
        System.out.println("Sheet number: " + fileinitial);
    }
    
    @DataProvider(name = "testdata")
    public static Object[][] readexcelretobj() throws Exception {
        Object[][] object = new Object[1][2];
        object[0][0] = "Nandan";
        object[0][1] = "123456";
    
        System.out.println("Data provider called...");
        System.out.println("Sheet number: " + fileinitial);
        return object;
     }
    }
    

    输出

    Static called...
    Sheet number: 2
    Data provider called...
    Sheet number: 2
    Test started
    Email: Nandan & Passowrd: 123456
    

    解决方案#2:

    你也可以使用@BeforeTest注解。

    Test

    @BeforeTest
    public void passSheetNumber() {
        new Excel_Util().assignSheetNumber(2);
    }
    
    @Test(dataProvider = "testdata", dataProviderClass = Excel_Util.class)
    public void testsignupdatafields(String email, String password) {
        System.out.println("Test started");
        System.out.println("Email: " + email + " & Passowrd: " + password);
    }
    

    Excel_Util

    public class Excel_Util {
    static int fileinitial;
    
    public void assignSheetNumber(int sheetNumber) {
        fileinitial = sheetNumber;
        System.out.println("Sheet number: " + fileinitial);
    }
    
    @DataProvider(name = "testdata")
    public static Object[][] readexcelretobj() throws Exception {
        Object[][] object = new Object[1][2];
        object[0][0] = "Nandan";
        object[0][1] = "123456";
    
        System.out.println("Data provider called...");
        System.out.println("Sheet number: " + fileinitial);
        return object;
     }
    }
    

    输出

    Sheet number: 2
    Data provider called...
    Sheet number: 2
    Test started
    Email: Nandan & Passowrd: 123456
    

    【讨论】:

    • 那么如果我想在数据提供者中传递值,需要使用构造函数传递值吗?我可以简单地在 atsheetindex() 方法中传递工作表编号。不需要构造函数。我想在运行时传递工作表的值,而不是像在数据提供者中那样硬编码值。我希望数据提供者代码是通用的。常见的。
    • 如果您再次看到输出可能会这样。您将了解 TestNG 的执行顺序,因此基于您需要工作。在执行测试块内的任何内容之前,数据提供程序代码将被执行,那么您的构造函数将如何被调用?
    • 任何关于我如何处理这个问题的提示都会有所帮助。我明白了这个命令。但无法找到解决方案。
    • 更新了解决方案。请查看并回复。
    • 其实我想从测试方法本身传递值。您在方法外部声明了一个静态变量,该值将被考虑。
    【解决方案2】:

    fileinitial=文件名; 奇怪的是,您没有收到有关无法从非静态上下文分配静态 int 的错误消息! 为什么不简单地从你的全局文件首字母中去掉静态。 *NB 有 int 问题的类是主类,如果你从 public static void main(String args[]) 调用,那将是不同的,不需要由构造函数分配,所以如果它不是主类,请删除静态来自变量“fileinitial”的关键字。

    或者构建一个静态类(总是嵌套子类)以将“非静态文件名参数”发送到(通过)静态方法,并将其作为静态分配从该方法返回。

    【讨论】:

      猜你喜欢
      • 2022-12-11
      • 1970-01-01
      • 2013-03-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-09-03
      • 2011-09-07
      • 1970-01-01
      相关资源
      最近更新 更多