Selenium未调用对应WebElement却触发NoSuchElementException异常排查
错误原因
Java类实例化时,所有成员变量的初始化操作会在构造方法、实例代码块执行前按声明顺序执行。你在NotificationsPage类中直接将notificationTitle声明为成员变量,并通过driver.findElement直接赋值初始化,只要你执行new NotificationsPage()实例化页面对象,无论后续是否调用使用该元素的方法,这行元素查找代码都会自动执行。此时如果当前页面不存在对应XPath的元素,就会直接抛出NoSuchElementException。
从报错堆栈也可以验证:错误触发在NotificationsPage的<init>(类实例初始化)阶段,刚好对应该元素初始化的代码行。
另外你测试用例中的try-catch仅捕获了ExceptionInInitializerError,而NoSuchElementException属于RuntimeException,不会被该捕获逻辑拦截,因此错误会直接抛出。
解决方案
方案1:使用PageFactory懒加载元素
Selenium官方提供的PageFactory默认采用懒加载策略,只有元素被首次调用时才会执行查找逻辑,不会在类初始化阶段就查找元素,修改代码如下:
public class NotificationsPage extends BasePage { // 构造方法中初始化PageFactory public NotificationsPage() { PageFactory.initElements(driver, this); } private final WebElement datePicker = driver.findElement(By.xpath("(//input[@aria-label='Password2'])[1]")); public String textBoxData = ""; public String date1 = ""; public String date2 = ""; // 用@FindBy注解声明元素,初始化阶段不会执行查找 @FindBy(xpath = "//a[@class='pmd-list-title']") private WebElement notificationTitle; { textBoxData = datePicker.getAttribute("value"); String[] parts = textBoxData.split("-"); date1 = parts[0].trim(); date2 = parts[1].trim(); } public String getNotificationTitle() { return notificationTitle.getText(); } }
方案2:手动实现懒加载
如果不使用PageFactory,可以将元素查找逻辑放到对应的调用方法中,只有方法被调用时才查找元素:
// 仅声明变量,初始化阶段不执行查找 private WebElement notificationTitle; public String getNotificationTitle() { notificationTitle = driver.findElement(By.xpath("//a[@class='pmd-list-title']")); return notificationTitle.getText(); }
方案3:拆分页面对象
如果notificationTitle元素不属于当前NotificationsPage对应的页面,建议将该元素和对应方法拆分到独立的页面对象类中,避免无关元素查找影响当前页面逻辑。
内容的提问来源于stack exchange,提问作者enthusiasticCoder
相关产品推荐
相关产品推荐

