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