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 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 - WebElements 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());
}