I'm having trouble with NullPointerExceptions when I try using static methods in a page object. If I do it with non-static methods, it works fine.
Non-static version:
public class ComplaintPage {
private ExtendedWebDriver driver;
@FindBy(css = "[data-selector=date-received-complaint]")
public WebElement dateComplaintReceoved;
public ComplaintPage() {
driver = Browser.extendedDriver();
PageFactory.initElements(driver, this);
}
public void setComplaintDate() {
dateComplaintReceoved.sendKeys(LocalDate.now().toString());
}
}
Calling code:
ComplaintPage complaintPage = new ComplaintPage;
complaintPage.setComplaintDate();
This works fine. The date field is set.
Static version
public class ComplaintPage {
private static ExtendedWebDriver driver;
@FindBy(css = "[data-selector=date-received-complaint]")
public static WebElement dateComplaintReceoved;
public ComplaintPage() {
driver = Browser.extendedDriver();
PageFactory.initElements(driver, this);
}
public void static setComplaintDate() {
* dateComplaintReceoved.sendKeys(LocalDate.now().toString());
}
}
Calling code:
ComplaintPage.setComplaintDate();
This does not work, and results in a java.lang.NullPointerException on the line marked with "*" (the line accessing the WebElement).
I kind of like using static methods like this in test, since I don't really see a problem with it, and it makes the code even more easy to read. And I've done it before, in C#/VS, but for some reason I'm missing something important here.
NullPointerException
is thrown because of how PageFactory
works. You see, when you create an instance of ComplaintPage
class, you are invoking its constructor:
public ComplaintPage() {
driver = Browser.extendedDriver();
PageFactory.initElements(driver, this);
}
The constructor calls initElements
method of PageFactory
class. This method initializes all of WebElement
and List<WebElement
> fields with Java Reflection API. It basically changes the default null
values to implementations of the interface. It also provides sort of Lazy instantiation of the WebElement which means - WebElement
s are found (looked for?) only when needed - when you invoke operations on them.
When you created static methods and static WebElements - you did not call the constructor of the class, which lead to NOT invoking the initElements
method.
All of the elements annotated with @FindBy
were not initialized. That's why it's not a good idea to use PageFactory with static methods.
Instead of using PageFactory you can just find the element with classic driver.findElement
inside the static method.
public void static setComplaintDate(WebDriver driver) {
driver.findElement(By.cssSelector("[data-selector=date-received-complaint]")).sendKeys(LocalDate.now().toString());
}