java.lang.ClassCastException:com.sun.proxy。$ Proxy8无法转换为org.openqa.selenium.internal.WrapsDriver

Pri*_*nal 4 java aspectj webdriver

我在AspectJ中有以下切入点和给出的建议

@Pointcut("(call(* org.openqa.selenium.WebElement.sendKeys(..)))")
    public void onWebElementAction() {
}

@After("onWebElementAction() && target(webelement)")
public void afterWebElementAction(JoinPoint joinPoint, WebElement webelement) {
    System.out.println(webelement.getAttribute("name")); //1
    WebDriver driver = ((WrapsDriver) webelement).getWrappedDriver(); //2
    //DO SOMETHING HERE
}
Run Code Online (Sandbox Code Playgroud)

在执行第1行时没有任何错误。在第2行,我收到错误消息

java.lang.ClassCastException: com.sun.proxy.$Proxy8 cannot be cast to org.openqa.selenium.internal.WrapsDriver
Run Code Online (Sandbox Code Playgroud)

投射在其他地方也可以正常工作。有人可以帮忙吗?

elb*_*loo 8

尽管标记为正确的答案确实指出了问题,但它没有解释问题,也没有提出确实存在的解决方案。让我首先在这里详细说明潜在问题,这是WebElement可以实例化的方式。

一方面,当通过WebElement调用实例化a时WebDriver#findElement,实际RemoteWebElement对象在那一刻被构造,但是,当WebElement通过实例化a 时PageFactory#initElements,实际的具体类对象(RemoteWebElement)并没有在此时创建,而是而是代理。

这是主要问题所在。代理对象没有实现该WrapsDriver接口,这就是抛出强制转换异常的原因,这非常好。但是,如果您好奇如何完成实际的代理创建(至少是通过默认装饰器完成),您将看到作为代理实例化的对象确实实现了WrapsElement提供该方法的接口getWrappedElement,您可以提取基础WebElement,然后以此为基础提取基础WebDriver,就像您尝试的那样。

现在,这里的关键是任何WebElement实例化的via WebDriver#findElement都不会实现,WrapsElement因为它是实际元素而不是代理,因此,在尝试使用之前WrapsElement#getWrappedElement,您首先需要检查所传递的WebElement是否实际上是代理。

您可以通过反射来实现,即

if(WrapsElement.class.isAssignableFrom(element.getClass()))
  webDriver = ((WrapsDriver)((WrapsElement)element).getWrappedElement()).getWrappedDriver();
else
  webDriver = ((WrapsDriver)element).getWrappedDriver();
Run Code Online (Sandbox Code Playgroud)

tl; dr WebElement您正在使用的实例是通过实例化的PageFactory#initElements,您首先需要提取基础WebElementWrapsElement#getWrappedElement然后再从中提取基础WebDriver