Java StaleElementReferenceException,即使使用'FluentWait<&燃气轮机`

Java StaleElementReferenceException,即使使用'FluentWait<&燃气轮机`,java,google-chrome,selenium,selenium-webdriver,webdriver,Java,Google Chrome,Selenium,Selenium Webdriver,Webdriver,我在ubto上运行webe2e测试(使用cucumber、junit、seleniumwebdriver) 使用remoteWebDriver时,我的测试偶尔会失败(使用本地webDriver时从不失败) 当我将代码重构为以下内容时,我认为我绕过了此异常: public String getSrcAfterWait(final By by) { WebElement webElement = getElementAfterWaitForDisplay2(by);

我在ubto上运行webe2e测试(使用cucumber、junit、seleniumwebdriver)

使用remoteWebDriver时,我的测试偶尔会失败(使用本地webDriver时从不失败)

当我将代码重构为以下内容时,我认为我绕过了此异常:

    public String getSrcAfterWait(final By by) {
        WebElement webElement = getElementAfterWaitForDisplay2(by);
        String currentSrc = null;
        if (webElement != null) {
            currentSrc = webElement.getAttribute("src");
        }
        return currentSrc;
    }


 public WebElement getElementAfterWaitForDisplay2(final By by) {
        Wait<WebDriver> wait = new FluentWait<>(driver)
                .withTimeout(30, TimeUnit.SECONDS)
                .pollingEvery(5, TimeUnit.SECONDS)
                .ignoring(NoSuchElementException.class, StaleElementReferenceException.class);

        return wait.until(ExpectedConditions.presenceOfElementLocated(by));
    }

如果页面是动态的,则可能发生以下情况

情景1。 在方法“getSrcAfterWait”中,您找到了带有“getElementAfterWaitForDisplay2”的元素。但是在调用webElement.getAttribute(“src”)之前,页面上的元素会发生变化。当您调用webElement.getAttribute(“src”)时,“webElement”指向一个已经过时(不再存在)的元素。这将导致StaleElementReferenceException

情景2。 也许你有一些动画。这样就可以周期性地多次创建元素的新实例。“getElementAfterWaitForDisplay2”总是为“By”条件查找元素,但有时它是页面上较新的对象。找到元素后,在调用webElement.getAttribute(“src”)之前,在页面上(在DOM中)创建了一个新实例。因此,您定位的变量引用已经过时的实例

两种情况下的简单解决方案是:捕获异常并再次定位对象


更复杂但更通用的解决方案:使用代理对象并在那里实现异常处理和定位。

@EladBenda:不太可能。你应该在一个循环中完成。但是您不需要编写循环代码。改用FluentWait。您只需将方法“getButtonTextAfterWait”转换为ExpectedCondition、谓词或函数,然后将其传递给FluentWait。您不需要显式捕获异常。您可以通过忽略(…Exception.class)来实现这一点,就像您在另一个地方所做的那样。它可以如下所示:

Wait wait = new FluentWait(driver)
  .withTimeout(60, SECONDS)
  .pollingEvery(5, SECONDS)
  .ignoring(NoSuchElementException.class, StaleElementReferenceException.class);

String text = wait.until(new Function() {
  public String apply(WebDriver driver) {
    WebElement element = driver.findElement(By.id("..."));
    return element.getText(); // or webElement.getAttribute("src")  etc.
  }
});

(1) 在
getElementAfterWaitForDisplay2
中请求
src
是否也能解决问题?(2)
捕获异常并再次定位对象
-建议我在catch块中再次调用
getsrcapterwait
?或者这里不推荐递归?嗯。您是否可以提供有关使用代理对象的更多详细信息?顺便说一句,可能是更接近的答案
  public String getButtonTextAfterWait(final By by) {
        String currentText;
        try {
            currentText = tryToGetText(by);

        } catch (StaleElementReferenceException ex)
        {
            currentText = tryToGetText(by);
        }
        return currentText;
    }
Wait wait = new FluentWait(driver)
  .withTimeout(60, SECONDS)
  .pollingEvery(5, SECONDS)
  .ignoring(NoSuchElementException.class, StaleElementReferenceException.class);

String text = wait.until(new Function() {
  public String apply(WebDriver driver) {
    WebElement element = driver.findElement(By.id("..."));
    return element.getText(); // or webElement.getAttribute("src")  etc.
  }
});
public void waitForElementBeDisplay(WebElement element) {


    Wait wait = new FluentWait(driver).withTimeout(Duration.ofSeconds(30)).ignoring(StaleElementReferenceException.class).pollingEvery(Duration.ofSeconds(2));
    wait.until(ExpectedConditions.refreshed(ExpectedConditions.visibilityOf(element)));

}