为什么在下面的方法中抛出StaleElementReferenceException?

问题描述:

我已经使用点击页面上的某些下拉菜单下面的方法:为什么在下面的方法中抛出StaleElementReferenceException?

protected void selectIthElementOffAllDropDowns(String selectElement, int entryOfDropdown) { 

    ICollection<IWebElement> allElements = driver.FindElements(By.CssSelector(selectElement)); 

    foreach(IWebElement element in allElements) { 
     if(element.IsDisplayed) { 
      new SelectElement(element).SelectByIndex(entryOfDropdown); 
     } 
    } 
} 

的代码按预期执行时间70%左右。但是,它偶尔会抛出一个StaleElementReferenceException。当这个被抛出它在该行抛出:

new SelectElement(element).SelectByIndex(entryOfDropdown); 

什么我不明白的是element.IsDisplayed怎么是真实的,但根据当元素已经完全或者删除被抛出此错误的硒文档here该元素不再附加到DOM。任何人都可以解释如何引发这个错误?另外,为什么if语句中的条件是真的,如果这个错误被正确地抛出?

注:我使用chromedriver运行这些测试与OpenQA.Selenium

这通常发生在发现的元素,做它的行动之间的页面重新加载。

在做任何动作之前,务必确保元素在那里。

在您使用foreach做一些动作与对象的列表/阵列/收藏,如果在任何时候在页面加载,然后这些对象丢失这种情况下,他们不会被视为附加到页面。

问题在于,在找到对象后,页面会更改状态或重新加载=>您有一个未连接到页面的对象,并且无法使用它。如果你有多个对象,并且你循环它们,那么陈旧元素的机会将会有更高的速度。

我不知道下面的例子有多正确:假设你有页面的对象/页面的一个实例,你搜索某个元素并且你有元素的对象,页面重新加载=>实例丢失并且新建一个,现在你有一些对象不会被记录到页面对象中,它们不会被附加到这个页面,类似的元素在那里,但不是你的对象,你将不得不寻找和为您的元素创建新对象。

它可以随时更改,包括在if条件被评估并输入if之后。