Java Selenium POM模式调用LoginPage方法报空指针异常问题
POM实现中空指针异常的根因与修复方案
异常根因
报错NullPointerException: Cannot invoke LoginPage.loginCustomer() because this.loginPage is null的核心触发原因是测试类中声明的页面对象从未实例化,代码中同时存在多个会导致编译/运行失败的隐藏问题:
- 测试类
TestPage仅声明了LoginPage、BankManagerMenu类型的成员变量,在@BeforeClass初始化流程中没有调用构造方法创建实例,类成员变量默认值为null,直接调用实例方法必然触发空指针。 - 基础类
_BasePage只定义了WebDriver、WebDriverWait的私有属性,没有实现带参构造方法,子类调用super(driver, driverWait)时会直接编译报错,对应的getter方法也未实现,子类无法访问父类的driver实例。 LoginPage中customerButton的XPath定位表达式缺少闭合右括号,属于语法错误,运行时会抛出定位表达式非法的异常。@BeforeClass中被注释的WebDriverWait定义是局部变量,即使放开注释也只会在方法内部生效,不会给类成员变量driverWait赋值,后续初始化页面对象时无法传入有效的wait实例。- ChromeDriver的路径字符串使用了未转义的反斜杠,Java会识别为非法转义字符,直接导致编译失败。
修复步骤
按以下顺序修正即可解决问题:
- 补全
_BasePage类的带参构造方法与属性getter方法,确保父类属性可以被正常赋值、被子类访问。 - 修正路径转义、XPath语法、局部变量遮蔽成员变量的低级错误。
- 在
@BeforeClass方法中完成driver和driverWait初始化后,显式实例化所有页面对象,传入已经初始化完成的driver与driverWait实例。
修正后完整代码
_BasePage.java(基础页类)
import org.openqa.selenium.WebDriver; import org.openqa.selenium.support.ui.WebDriverWait; public class _BasePage { private WebDriver driver; private WebDriverWait driverWait; public _BasePage(WebDriver driver, WebDriverWait driverWait) { this.driver = driver; this.driverWait = driverWait; } public WebDriver getDriver() { return driver; } public WebDriverWait getDriverWait() { return driverWait; } }
LoginPage.java(登录页类)
import org.openqa.selenium.By; import org.openqa.selenium.WebDriver; import org.openqa.selenium.support.ui.ExpectedConditions; import org.openqa.selenium.support.ui.WebDriverWait; import java.time.Duration; public class LoginPage extends _BasePage { // 修正XPath缺失的右括号 private By customerButton = By.xpath("//*[contains(text(), 'Customer Login')]"); private By bankManagerButton = By.xpath("//*[contains(text(), 'Bank Manager Login')]"); public LoginPage(WebDriver driver, WebDriverWait driverWait) { super(driver, driverWait); } public void loginBankManager() { new WebDriverWait(getDriver(), Duration.ofSeconds(20)) .until(ExpectedConditions.elementToBeClickable(bankManagerButton)) .click(); } public void loginCustomer() { getDriver().findElement(customerButton).click(); } }
TestPage.java(测试类)
import org.openqa.selenium.WebDriver; import org.openqa.selenium.chrome.ChromeDriver; import org.openqa.selenium.support.ui.WebDriverWait; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; import java.time.Duration; public class TestPage { private WebDriver driver; private WebDriverWait driverWait; private LoginPage loginPage; private BankManagerMenu bankManagerMenu; @BeforeClass public void beforeClass(){ // 转义路径中的反斜杠 System.setProperty("webdriver.chrome.driver", "C:\\Users\\Raven\\Desktop\\QA\\chromedriver.exe"); driver = new ChromeDriver(); driver.manage().window().maximize(); // 给类成员变量赋值,不要定义同名局部变量 driverWait = new WebDriverWait(driver, Duration.ofSeconds(15)); driver.navigate().to("https://www.globalsqa.com/angularJs-protractor/BankingProject/#/login"); // 核心:实例化所有页面对象,传入已初始化的驱动实例 loginPage = new LoginPage(driver, driverWait); bankManagerMenu = new BankManagerMenu(driver, driverWait); } @Test public void loginAsBankManager(){ loginPage.loginBankManager(); // 放开注释即可正常执行断言 // Assert.assertTrue(bankManagerMenu.addCustomerBtn()); } }
补充说明:
BankManagerMenu类本身无语法错误,父类构造方法补全后即可正常运行。注意该类中使用了写死的绝对XPath定位元素,前端结构稍有变动就会定位失败,建议替换为基于文本、相对路径的稳定定位方式。
内容的提问来源于stack exchange,提问作者Marina Biro
相关产品推荐
相关产品推荐

