Home > Software engineering >  Why is the constructor not taking a value passed during object creation?
Why is the constructor not taking a value passed during object creation?

Time:11-03

I am writing a code wherein I am operating with an excel file having three sheets. I am using Apache POI and Data provider annotation for data driven approach. I wanted to pass Sheet index number or Sheet name at run time but I was not able to do it setting a parameter to data provider method. So what I did is I wrote a constructor and a static variable as integer. In parameterized constructor, I initialized that static variable and then in my test case, by creating object of the class which had data provider method, I passed an integer that is, sheet index from which I wanted the data to be taken to run the test. But every time, the constructor is taking value as 0. I don't know why. Below is the data driven code and constructor I have written.

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;
        }
    

The test case which I wrote is as follows.

@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");}
    }
}

Here, I have passed 2 at the time of object creation but every time, the values are taken from the first sheet. That is, sheet index 0 is considered every time. I don't want to hard code any value in excelutil class code as I wanted to behave it as generic code. So in test case itself I decided to pass sheet number. I am confused what to do and wanted a reason why this is happening and what is the mistake I am doing. Can anyone please guide me with this ?

CodePudding user response:

I simplified the code to replicate the issue.

Existing code :

@Test method:

@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;
 }
}

Output:

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

If you see the above output the DataProvider code is being called first so your value is passing as 0. To fix this call the new Excel_Util(2); object into DataProvider

Updated code :

@Test method:

@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;
 }
}

Output:

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

If you see the above output now the constructor is being called first.

Solution#1:

As we discussed if you want to pass the value from Test class then you can do something like this. Instead of a constructor use static block.

Test class:

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;
 }
}

Output:

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

Solution#2:

You can use @BeforeTest annotation as well.

Test class:

@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;
 }
}

Output:

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

CodePudding user response:

fileinitial=filename; It's a wonder you did not get an error message about a static int cannot be assigned from a non static context! Why not simply take static off your global fileinitial. *NB the class with the int problem were the main class and if you were calling from public static void main(String args[]) that would be different and not require assigning by the constructor, so if it is not the main class remove static keyword from variable "fileinitial".

Or build a static class (always nested subclass) to send the "non static filename argument" into (through) a static method and return it as static assignment from that method.

  • Related