我在 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
}

虽然第 1 行执行时没有任何错误。在第 2 行我收到错误
java.lang.ClassCastException: com.sun.proxy.$Proxy8 cannot be cast to org.openqa.selenium.internal.WrapsDriver

类型转换在其他地方工作没有问题。
有人可以帮忙吗?

最佳答案

虽然标记为正确的答案确实指出了问题,但它并没有解释问题,也没有提出实际存在的解决方案。让我首先详细介绍一下这里的潜在问题,即 WebElement 可以被实例化的方式。

一方面,当 WebElement 作为调用 WebDriver#findElement 的结果被实例化时,实际的 RemoteWebElement 对象在那一刻被构造,然而,当 WebElement 通过 PageFactory#initElements 被实例化时,实际的具体类对象( RemoteWebElement )不会在那一点上被创建,而是一个代理。

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

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

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

if(WrapsElement.class.isAssignableFrom(element.getClass()))
  webDriver = ((WrapsDriver)((WrapsElement)element).getWrappedElement()).getWrappedDriver();
else
  webDriver = ((WrapsDriver)element).getWrappedDriver();

tl;博士
您正在使用的 WebElement 实例是通过 PageFactory#initElements 实例化的,您首先需要使用 WebElement 提取底层 WrapsElement#getWrappedElement,然后从中提取 WebDriver

关于java.lang.ClassCastException : com. sun.proxy.$Proxy8 无法转换为 org.openqa.selenium.internal.WrapsDriver,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/18206578/

10-11 07:44