I am trying to get the driver that was set in the ThreadLocal in the "BaseTest" class to my Test class "T001_LoginTests_Check" while creating an object of my Page class "HomePage_Check". I am passing the driver through the constructor defined in the Page class.
This is what I have done so far and issue I am facing as follows:
I have created a thread safe driver in my "BaseTest" class. Whenever I am going to get the driver stored in the ThreadLocal in my Test class that inherits the "BaseTest" class, I get a NullPointerException.
My "BaseTest" class is as follows:
package base;
import io.github.bonigarcia.wdm.WebDriverManager;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import org.openqa.selenium.edge.EdgeOptions;
import org.openqa.selenium.firefox.FirefoxOptions;
import org.openqa.selenium.remote.AbstractDriverOptions;
import org.testng.annotations.AfterSuite;
import org.testng.annotations.BeforeSuite;
import java.io.FileInputStream;
import java.util.Properties;
public class BaseTest {
public WebDriver driver;
Properties prop;
public BaseTest(){
loadProperties();
}
public static final ThreadLocal<WebDriver> tsDriver = new ThreadLocal<>();
private void setDriver(WebDriver driver){
tsDriver.set(driver);
}
public static synchronized WebDriver getDriver(){
return tsDriver.get();
}
public WebDriver getBrowser(){
AbstractDriverOptions absOptions;
String browser = prop.getProperty("browser");
if (browser.equalsIgnoreCase("Chrome")){
absOptions = new ChromeOptions();
driver = WebDriverManager.chromedriver().capabilities(absOptions).create();
} else if (browser.equalsIgnoreCase("Firefox")) {
absOptions = new FirefoxOptions();
driver = WebDriverManager.firefoxdriver().capabilities(absOptions).create();
} else if (browser.equalsIgnoreCase("Edge")) {
absOptions = new EdgeOptions();
driver = WebDriverManager.edgedriver().capabilities(absOptions).create();
} else {
System.out.println("[i] Invalid argument! Spawning Chrome Driver as default.");
absOptions = new ChromeOptions();
driver = WebDriverManager.chromedriver().capabilities(absOptions).create();
}
return driver;
}
public void loadProperties() {
prop = new Properties();
try{
FileInputStream fis = new FileInputStream("D:\\SQA\\webdriver_java\\rokomari.com_automation" +
"\\src\\test\\java\\config\\config.properties");
prop.load(fis);
}catch (Exception e){
System.out.println("[!] Some unexpected error occurred during loading the properties file.");
}
}
@BeforeSuite
public void setUp(){
driver = getBrowser();
driver.get(prop.getProperty("url"));
driver.manage().window().maximize();
setDriver(driver);
}
@AfterSuite
public void cleanUp(){
getDriver().quit();
}
}
And my Test class is as follows. Please note that I'm passing the driver to the page class while creating an object for my Page class and trying to receive the driver by the Page class constructor.
package tests;
import base.BaseTest;
import org.openqa.selenium.WebDriver;
import org.testng.annotations.Test;
import pages.HomePage_Check;
public class T001_LoginTests_Check extends BaseTest {
HomePage_Check homePageCheck = new HomePage_Check(getDriver());
@Test
public void pageTitleTest(){
System.out.println("[?] Called from test class -> " + driver);
homePageCheck.getPageTitle();
}
}
I am also putting my Page class below for better understanding:
package pages;
import org.openqa.selenium.WebDriver;
public class HomePage_Check {
public WebDriver driver;
public HomePage_Check(WebDriver driver){
this.driver = driver;
}
public void getPageTitle(){
System.out.println(driver.getTitle());
}
}
My config.properties file contains following data:
browser = Chrome url = https://www.rokomari.com/book
My code is generating the following error:
java.lang.NullPointerException: Cannot invoke "org.openqa.selenium.WebDriver.getTitle()" because "this.driver" is null
at pages.HomePage_Check.getPageTitle(HomePage_Check.java:19)
at tests.T001_LoginTests_Check.pageTitleTest(T001_LoginTests_Check.java:14)
at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:104)
at java.base/java.lang.reflect.Method.invoke(Method.java:578)
at org.testng.internal.invokers.MethodInvocationHelper.invokeMethod(MethodInvocationHelper.java:139)
at org.testng.internal.invokers.TestInvoker.invokeMethod(TestInvoker.java:677)
at org.testng.internal.invokers.TestInvoker.invokeTestMethod(TestInvoker.java:221)
at org.testng.internal.invokers.MethodRunner.runInSequence(MethodRunner.java:50)
at org.testng.internal.invokers.TestInvoker$MethodInvocationAgent.invoke(TestInvoker.java:969)
at org.testng.internal.invokers.TestInvoker.invokeTestMethods(TestInvoker.java:194)
at org.testng.internal.invokers.TestMethodWorker.invokeTestMethods(TestMethodWorker.java:148)
at org.testng.internal.invokers.TestMethodWorker.run(TestMethodWorker.java:128)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
at org.testng.TestRunner.privateRun(TestRunner.java:829)
at org.testng.TestRunner.run(TestRunner.java:602)
at org.testng.SuiteRunner.runTest(SuiteRunner.java:437)
at org.testng.SuiteRunner.runSequentially(SuiteRunner.java:431)
at org.testng.SuiteRunner.privateRun(SuiteRunner.java:391)
at org.testng.SuiteRunner.run(SuiteRunner.java:330)
at org.testng.SuiteRunnerWorker.runSuite(SuiteRunnerWorker.java:52)
at org.testng.SuiteRunnerWorker.run(SuiteRunnerWorker.java:95)
at org.testng.TestNG.runSuitesSequentially(TestNG.java:1256)
at org.testng.TestNG.runSuitesLocally(TestNG.java:1176)
at org.testng.TestNG.runSuites(TestNG.java:1099)
at org.testng.TestNG.run(TestNG.java:1067)
at com.intellij.rt.testng.IDEARemoteTestNG.run(IDEARemoteTestNG.java:66)
at com.intellij.rt.testng.RemoteTestNGStarter.main(RemoteTestNGStarter.java:105)
All I want is to pass the driver from ThreadLocal through my Test class while creating an object of my Page class and the driver will be received by the Page class constructor. That's it.
Try this below code approach and I hope it clears your issue.
package tests;
import base.BaseTest;
import org.openqa.selenium.WebDriver;
import org.testng.annotations.Test;
import pages.HomePage_Check;
public class T001_LoginTests_Check extends BaseTest {
HomePage_Check homePageCheck;
@Test
public void pageTitleTest()
{
homePageCheck = new HomePage_Check(getDriver());
System.out.println("[?] Called from test class -> " + driver);
homePageCheck.getPageTitle();
}
}