NPE on constructor invocation

I have the following java class (implements the page object template)

package core.pageObjects;

import org.openqa.selenium.*;

public class ConsultaClientePorDocumento {

    private WebDriver driver;

    public ConsultaClientePorDocumento(WebDriver d){
        this.driver = d;
    }

    public WebElement cancelarButton = driver.findElement(By.id("Cancelar"));
}

      

Then I try to use it in my test like this:

import core.pageObjects.*;

ConsultaClientePorDocumento consultaCPD = new ConsultaClientePorDocumento(driver);

      

And I am getting the following error:

java.lang.NullPointerException
at core.pageObjects.ConsultaClientePorDocumento.<init>(ConsultaClientePorDocumento.java:16)

      

What am I doing wrong?

+3


source to share


2 answers


Fields are initialized before the body of the constructor (except for any explicit or implicit invocation of the superclass constructor). This means that it is driver

not initialized by the constructor during initialization cancelarButton

; it is still the default null

.

Place your initialization code cancelarButton

in the post-initialization constructor driver

to make sure it's driver

initialized before you need it in the initialization code for cancelarButton

.

private WebDriver driver;

public ConsultaClientePorDocumento(WebDriver d){
    this.driver = d;
    this.cancelarButton = driver.findElement(By.id("Cancelar"));
}

public WebElement cancelarButton;

      



The JLS, section 12.5 , defines this behavior:

Before the result is a reference to the newly created object, the specified constructor is processed to initialize the new object using the following procedure:

  • Assign the constructor arguments to the newly created parameter variables for this constructor call.

  • If this constructor begins by explicitly calling a constructor (§8.8.7.1) of another constructor in the same class (using this), then evaluate the arguments and process the constructor call recursively using these five steps. If the call to the constructor ends abruptly, then this procedure ends abruptly for the same reason; otherwise, go to step 5.

  • This constructor does not start by explicitly calling the constructor of another constructor in the same class (using this). If this constructor is of a class other than Object, then this constructor will start by explicitly or implicitly calling the superclass's constructor (using super). Evaluate the arguments and process the superclass constructor call recursively using these five steps. If the constructor call completes abruptly, then this procedure completes abruptly for the same reason. Otherwise, go to step 4.

  • Implement instance initializers and instance variable initializers for this class by assigning the values ​​of the instance variable initializers to the corresponding instance variables in the left-to-right order in which they appear as text in the source code for the class. If execution of any of these initializers results in an exception, then no new initializers are processed, and this procedure terminates abruptly with the same exception. Otherwise, go to step 5.

  • Execute the rest of this constructor . If this execution ends abruptly, then this procedure ends abruptly for the same reason. Otherwise, this procedure works fine.

I have highlighted the last step, which is to execute the rest of the constructor.

+7


source


You are trying to use driver

before it was set by the constructor. Move the initialization cancelarButton

to the constructor:

public ConsultaClientePorDocumento(WebDriver d){
    this.driver = d;
    cancelarButton = driver.findElement(By.id("Cancelar"));
}

public WebElement cancelarButton;

      



It doesn't matter where the fields are in the file, they will all be evaluated before calling the constructor.

+3


source







All Articles