You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Selenium自动化脚本调试报错:hover元素失败,ClassCastException求助

Selenium登录自动化脚本ClassCastException问题排查

问题背景

我编写了一个基于Selenium的登录页自动化脚本,采用页面对象与方法类、可复用组件类、测试类的分离结构。运行脚本时抛出ClassCastException异常,调试模式下hover测试代码中的in_username对象时也会报错,尝试创建WebElement对象未解决问题,需协助排查。

代码结构

页面对象与方法类

public class LoginPage extends ReusableComponents {
    WebDriver driver;
    
    @FindBy(xpath="//input[@name='username']")
    public WebElement in_username;
    
    @FindBy(xpath="//input[@name='password']")
    WebElement in_password;
    
    @FindBy(xpath="//button[@type='submit']")
    WebElement btn_submit;
    
    public LoginPage(WebDriver driver) {
        super(driver);
        this.driver = driver;
        PageFactory.initElements(driver, this);
    }
    
    public void enterUname(String uname)  {
        in_username.sendKeys(uname);
    }
    
    public void enterPassword(String pass) {
        in_password.sendKeys(pass);
    }
    
    public void clickSubmit() {
        btn_submit.click();
    }   
}

可复用组件类

public class ReusableComponents {
    
    WebDriver driver;

    public ReusableComponents(WebDriver driver) {
        this.driver = driver;
    }
    
    public void setup()  {
        WebDriverManager.chromedriver().setup();
        driver = new ChromeDriver();
        driver.manage().window().maximize();
        driver.get("https://opensource-demo.orangehrmlive.com/web/index.php/auth/login");
    }

    public void waitElementToAppear(WebElement findby){
        
        WebDriverWait wait = new WebDriverWait(driver, 30);
        wait.until(ExpectedConditions.visibilityOfElementLocated((By) findby));
                
    }
    
    public void closeBrowser() {
        driver.close();
    }   
}

测试类

public class OpenBrowser {
    static WebDriver driver;

    public static void main(String[] args) {
        
        LoginPage login = new LoginPage(driver);
        ReusableComponents common = new ReusableComponents(driver);
        common.setup();
        common.waitElementToAppear(login.in_username);
        login.enterUname("Admin");
        login.enterPassword("admin123");
        login.clickSubmit();
        common.closeBrowser();
        
    }
}

错误日志

SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
Starting ChromeDriver 114.0.5735.90 (386bc09e8f4f2e025eddae123f36f6263096ae49-refs/branch-heads/5735@{#1052}) on port 31559
Only local connections are allowed.
Please see https://chromedriver.chromium.org/security-considerations for suggestions on keeping ChromeDriver safe.
ChromeDriver was started successfully.
Jun 29, 2023 8:43:53 AM org.openqa.selenium.remote.ProtocolHandshake createSession
INFO: Detected dialect: W3C
Exception in thread "main" java.lang.ClassCastException: class jdk.proxy2.$Proxy4 cannot be cast to class org.openqa.selenium.By (jdk.proxy2.$Proxy4 is in module jdk.proxy2 of loader 'app'; org.openqa.selenium.By is in the unnamed module of loader 'app')
    at com.orange.reusablecomponents.ReusableComponents.waitElementToAppear(ReusableComponents.java:32)
    at com.orangehrm.OpenBrowser.main(OpenBrowser.java:27)

错误截图

错误截图

问题原因与修复方案

核心问题

  1. 类型转换错误:waitElementToAppear方法接收WebElement参数,却强制将其转为By类型——两者是完全独立的类,无法直接转换,这是抛出ClassCastException的直接原因。
  2. driver初始化顺序错误:测试类中先创建LoginPage实例,此时driver还是null,后续setup方法才初始化driver,导致LoginPage中的元素无法正确绑定到有效driver上。

修复步骤

1. 修正可复用组件类的等待方法

选择以下两种方案之一:

方案一:接收By类型定位器
public void waitElementToAppear(By locator){
    // Selenium 4+推荐使用Duration设置超时
    WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(30));
    wait.until(ExpectedConditions.visibilityOfElementLocated(locator));
}

对应页面对象类需要新增By类型的定位器:

public class LoginPage extends ReusableComponents {
    @FindBy(xpath="//input[@name='username']")
    public By usernameLocator;
    
    @FindBy(xpath="//input[@name='username']")
    public WebElement in_username;
    
    // 其余代码不变
}

测试类中调用方式改为:

common.waitElementToAppear(login.usernameLocator);
方案二:直接等待WebElement可见
public void waitElementToAppear(WebElement element){
    WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(30));
    wait.until(ExpectedConditions.visibilityOf(element));
}

此方案无需修改页面对象类,直接沿用原有调用方式即可。

2. 调整测试类的初始化顺序

先执行setup初始化driver,再创建LoginPage实例:

public class OpenBrowser {
    static WebDriver driver;

    public static void main(String[] args) {
        ReusableComponents common = new ReusableComponents(driver);
        common.setup();
        // 确保driver初始化完成后再创建LoginPage
        LoginPage login = new LoginPage(common.driver);
        common.waitElementToAppear(login.in_username);
        login.enterUname("Admin");
        login.enterPassword("admin123");
        login.clickSubmit();
        common.closeBrowser();
    }
}

3. 优化页面对象类的driver管理

由于LoginPage继承了ReusableComponents,无需重复声明driver变量:

public class LoginPage extends ReusableComponents {
    @FindBy(xpath="//input[@name='username']")
    public WebElement in_username;
    
    @FindBy(xpath="//input[@name='password']")
    WebElement in_password;
    
    @FindBy(xpath="//button[@type='submit']")
    WebElement btn_submit;
    
    public LoginPage(WebDriver driver) {
        super(driver);
        PageFactory.initElements(driver, this);
    }
    
    // 其余方法不变
}

内容的提问来源于stack exchange,提问作者Test Bite

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 10:54:56