Reputation: 63
my code looks in the next way:
Parent class:
package TestPackageForStructure;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
public class PageElements {
WebDriver driver;
public PageElements(WebDriver driver) {
this.driver = driver;
}
WebElement searchBox = driver.findElement(By.xpath("//*[@id=\"APjFqb\"]"));
}
Child class:
package TestPackageForStructure;
import io.qameta.allure.Step;
import org.openqa.selenium.WebDriver;
public class PageSteps extends PageElements {
public PageSteps(WebDriver driver) {
super(driver);
}
@Step
public void inputData(String text) {
searchBox.sendKeys("Hello");
}
Test class:
import TestPackageForStructure.PageSteps;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.testng.annotations.Test;
public class TestStructure {
@Test
public void insertSomeData() throws InterruptedException {
WebDriver driver = new ChromeDriver();
PageSteps pageSteps = new PageSteps(driver);
driver.get("https://www.google.com/");
Thread.sleep(5000);
pageSteps.inputData("Hello World");
}
}
Error: java.lang.NullPointerException: Cannot invoke "org.openqa.selenium.WebDriver.findElement(org.openqa.selenium.By)" because "this.driver" is null
So to say it shortly, I'm throwing my instance of a WebDriver to a parent class by using the super keyword in the child constructor but the driver is still null
I was expecting the driver to be passed to a parent class and an instance of WebElement to be created without any daviations (driver not being null)
Upvotes: 0
Views: 157
Reputation: 15186
The fields of a class are initialised before the constructor(s). Here is a simple example which demonstrates - I've swapped WebDriver
for String
, and added a few println to show values. These ought to be executed in order 1,2,3,4:
class PageElements {
{ System.out.println("1 "+this); }
String driver ; //= "this";
public PageElements(String driver) {
this.driver = driver;
System.out.println("3 "+this);
}
// At this point driver is still null
{ System.out.println("2 "+this); }
int searchBox = driver.length();
public String toString() {
return "PageElements[driver="+driver+" searchBox="+searchBox+']';
}
public static void main(String... args) {
System.out.println("4 "+new PageElements("this and that"));
}
}
The field value searchBox
is initialised when driver is null - hence your NullPointerException
and you will see the output:
1 PageElements[driver=null searchBox=0]
2 PageElements[driver=null searchBox=0]
Exception in thread "main" java.lang.NullPointerException: Cannot invoke "String.length()" because "this.driver" is null
Change the declaration of driver
to String driver = "this";
and it will print 1,2,3,4 showing that searchBox is defined using the old value "this":
1 PageElements[driver=null searchBox=0]
2 PageElements[driver=this searchBox=0]
3 PageElements[driver=this and that searchBox=4]
4 PageElements[driver=this and that searchBox=4]
So, the answer by ControlAltDel shows the correct way to initialise searchBox
. Making both fields final
and set in constructor may help.
Upvotes: 2
Reputation: 35096
I believe this should fix your code:
WebElement searchBox;
public PageElements(WebDriver driver) {
this.driver = driver;
searchBox = driver.findElement(By.xpath("//*[@id=\"APjFqb\"]"));
}
The problem you are having is that driver
is not set yet the way you are doing it.
Upvotes: 2