Davit Ebralidze
Davit Ebralidze

Reputation: 63

I am passing an instance of a WebDriver to a parent class with super() keyword, but yet I'm getting nullpointerexeption

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

Answers (2)

DuncG
DuncG

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

ControlAltDel
ControlAltDel

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

Related Questions