Search code examples
javaseleniumselenium-webdriverpageobjects

Page Object Model seeing null pointer exception when running my tests?


When triggering my test I seem to be seeing a null pointer exception when trying to interact with my Page Factory WebElement.

Code contained within my DriverFactory:

public class DriverFactory {
    private static DriverFactory instance = null;
    public static ThreadLocal<WebDriver> webDriver = new ThreadLocal<WebDriver>();

    public static DriverFactory getInstance() {
        if ( instance == null ) {
            instance = new DriverFactory();
        }
        return instance;
    }

    public static final void setDriver(String browser) {
        switch (browser) {

        case "firefox":
                System.setProperty("webdriver.gecko.driver", 
                Global_VARS.FIREFOX_DRIVER_DIRECTORY);
                webDriver.set(new FirefoxDriver());
            break;

        case "chrome":
                System.setProperty("webdriver.chrome.driver", 
                Global_VARS.CHROME_DRIVER_DIRECTORY);
                webDriver.set(new ChromeDriver());
            break;
        }
        getDriver().manage().timeouts().implicitlyWait(20, TimeUnit.SECONDS);
        getDriver().manage().window().maximize();
    }

    public static WebDriver getDriver() {
        return webDriver.get();
    }

    public static void tearDown() {
        getDriver().quit();
    }
}

Code contained within my base page:

public abstract class BasePO<T>  {
    private @FindBy(xpath = "//a[text()='Log in']") WebElement logIn_button;
    protected WebDriver driver;

    public BasePO() {
        this.driver = DriverFactory.getDriver();
        PageFactory.initElements(this.driver, this);
    }

    public void openHomepage() {
        driver.get("https://stackoverflow.com/");
    }

    public void baseClickOnLoginButton() {
        logIn_button.click();
    }
}

Code contained within my BaseTest class:

public class BaseTest {
    public SubPage subPage;
    public BasePO<?> basePage;

    @BeforeClass
    public void pomSetup() {
        subPage = PageFactory.initElements(DriverFactory.getDriver(), SubPage.class);
        basePage = PageFactory.initElements(DriverFactory.getDriver(), BasePO.class);
    }

    @BeforeMethod
    public void setup() {
        DriverFactory.setDriver("chrome");

        //works
        //subPage.openHomepage();
    }

    @AfterMethod
    public void tearDown() {
        if (DriverFactory.getDriver() != null) {
            DriverFactory.tearDown();
        }
    }

The code which form's my Test case:

public class Test1 extends BaseTest {
    @Test
    public void exampleTest1() throws InterruptedException {
        subPage.openHomepage(); //works as expected

        subPage.clickOnLoginButton(); //Exception here, null pointer 
    }
}

When trigger my TestNg test its the openHomePage method works, in turn opening the specified url; which uses DriverFactory.getDriver().get() however when attempting to click on a Page Factory element such as calling: logIn_button.click(); within my test I seem to be receiving a null pointer exception even though I have initialised the class?


Solution

  • In the @BeforeClass, you have initialized the Page factory before you created the driver instance. If you move the code in pomSetup() to the setup() method after the DriverFactory.setDriver("chrome"); the test code should work. Also, in the BasePO class you have initialized the page factory in the constructor, so calling new in the BaseTest Class will be enough.

    @BeforeClass
    public void pomSetup() {
    
    }
    
    @BeforeMethod
    public void setup() {
        DriverFactory.setDriver("chrome");
        // Page factory initialized the constructor of BasePO class
        subPage = new SubPage();
    }