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?
source to share
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.
source to share
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.
source to share