1
votes

For some reason, when I call method Spage.editExButton(int ID), I get an error saying that WebElement first is null. Why is it null? I have defined it using the @FindBy annotation. I have to explicitly define the element using findElement(By.id("xxx")) in order to be able to click on it. But why am I unable to call it using the @FindBy notation?

public class SPage extends GPage<SPage> {

    public SPage() {
        super();
    }

    public SPage(String pageType) {
        super(pageType);
    }

    @FindBy(id = "xxx")
    WebElement first;

    public WebElement eButton(int ID) {
        first.click();
        String tmp = ID + "-Edit";
        WebElement edit = getDriver().findElement(By.id(tmp));
        return edit;
    }

    public EPage cEdit(int ID) {
        eButton(ID).click();
        return new EPage(getBasePageType()).openPage(EPage.class);
    }
}

I am calling the method like this:

static EPage epage;
static SPage spage;

@Test
public void edit_exception() {
             epage = spage.cEdit(IDbefore);
}
4
From the give code, it looks like you have not initialized WebElement first so by default its null throwing NPE for first.click(); - Smit
How are you creating this instance of SPage? Is it given to you by Selenium? - Sotirios Delimanolis
I have added more information on how I call my method. - user2611836

4 Answers

8
votes

You need to call this (preferably in your constructors):

PageFactory.initElements(getDriver(), this);

More information: https://code.google.com/p/selenium/wiki/PageFactory

1
votes

As all other answer mentions that we have to initialize webElements using PageFactory.initElements(),

There are two ways of doing it or rather two places where it can be done :

1) inside class SPage :

As there are two constructors in SPage class we have to add following code to initailize all the elements declared in this class, it should be done in both class because we don't know that which constructor will be used to initialize SPage:

We will be passing driver instance to SPage class constructors, which will look like below :

public SPage(WebDriver driver) {
    super();
    PageFactory.initElements(driver, this);
}

public SPage(String pageType, WebDriver driver) {
    super(pageType);
    PageFactory.initElements(driver, this);
}

2) inside Other classes where SPage WebElements are to be used :

in the above example elementsCan be initialzed in the class where edit_exception() method is written, in short before anyplace we want to use elements/actions of the class SPage , Now the code will look like below:

@Test
public void edit_exception() {
             spage =  PageFactory.initElements(driver, SPage.class);  //we are not passing driver instance to SPage class
             epage = spage.cEdit(IDbefore);
}
0
votes

In my test class I added the following line of Code

WebMainMenu mainmenu = PageFactory.initElements(driver, WebMainMenu.class);

mainmenu.doStuff(driver, 5);

etc

I agree as per above that you need to instantiate the page object.

0
votes
WebElement first;

is null because element is not initialize when we are instantiating our page class. So initialize all elements in page class

 PageFactory.initElements(driver,  this);