4

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

铸造在其他地方工作没有问题。有人可以帮忙吗?

4

2 回答 2

8

虽然标记为正确的答案确实指出了问题,但它没有解释问题,也没有提出实际存在的解决方案。让我首先在此处提供有关潜在问题的更多详细信息,这是WebElement可以实例化的方式。

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

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

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

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

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

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

于 2016-10-17T20:34:07.573 回答
1

这是一个疯狂的猜测,因为我没有看到它真正起作用的案例。从异常看来,传递给的 WebElement 似乎afterWebElementAction是通过PageFactory. 我的猜测是,如果您将派生自 driver.findElement(), 的 WebElement 传递给afterWebElementAction,则不会出现强制转换异常。这就是它在其他情况下最有可能为您工作的方式。

于 2013-08-13T17:25:14.103 回答