Comment prévenir StaleElementReferenceException dans PageFactory dans Selenium C #?

J’ai un modèle d’object de page Selenium WebDriver en C # 6. Je suis confronté à des StaleElementReferenceException lorsque je tente de cliquer sur des éléments de la barre de navigation chargés en ajax. C’est déroutant, car j’utilise PageFactory , sans aucun [CacheLookup] .

Voici le code en question. J’ai essayé de simplifier uniquement les parties importantes. (En fait, je passe un Driver , un wrapper autour de IWebDriver .) MenuBar.SelectEnglish() lève l’exception.

 public class Tests { [Test] public void SelectEnglishTest() { homePage .MenuBar.SelectEnglish(); } // ... } public class MenuBar : PageObject { [FindsBy(How = How.CssSelector, Using = "...")] private IWebElement Language { get; set; } [FindsBy(How = How.CssSelector, Using = "...")] private IWebElement English { get; set; } public T SelectEnglish() where T : Page { Language.Click(); IWait wait = new WebDriverWait(Driver, TimeSpan.FromSeconds(5)); wait.Until(ExpectedConditions.ElementToBeClickable(English)); English.Click(); Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo("en-US"); return (T)Activator.CreateInstance(typeof(T), Driver); } // ... } public class HomePage : PageObject { public MenuBar MenuBar { get; private set; } // ... } public class PageObject { protected IWebDriver Driver { get; } protected PageObject(IWebDriver driver) { Driver = driver; PageFactory.InitElements(this, new RetryingElementLocator(Driver, TimeSpan.FromSeconds(20))); } // ... } 

Qu’est ce qui cause cette erreur? Que puis-je faire à ce sujet?

De la docs, exception de référence d’élément obsolète

 A stale element reference exception is thrown in one of two cases, the first being more common than the second: - The element has been deleted entirely. - The element is no longer attached to the DOM. 

Puisque vous avez mentionné que l’élément est chargé à l’aide d’Ajax, l’élément a probablement changé après que votre object de page l’ait récupéré. Récupérez-le à nouveau ou attendez que Ajax soit terminé avant d’extraire les éléments affectés.


EDIT 1

Voici un exemple de code montrant comment extraire un élément à l’aide d’une méthode, même avec PageFactory.

 using OpenQA.Selenium; using OpenQA.Selenium.Firefox; using OpenQA.Selenium.Support.PageObjects; using System; namespace C_Sharp_Selenium_Test { class Program { static void Main(ssortingng[] args) { FirefoxDriver driver = new FirefoxDriver(); driver.Navigate().GoToUrl("http://www.google.com"); HomePage homePage = new HomePage(driver); PageFactory.InitElements(driver, homePage); homePage.search("stack overflow"); homePage.getSearchBox().Clear(); homePage.getSearchBox().SendKeys("c# pagefactory"); homePage.getSearchButton().Click(); } } public class HomePage { private By searchBox = By.Id("lst-ib"); private By searchButton = By.Name("btnG"); // add other elements in here that use FindsBy() to be loaded using PageFactory.InitElements() private IWebDriver driver; public void search(Ssortingng s) { getSearchBox().SendKeys(s); getSearchButton().Click(); } public IWebElement getSearchBox() { return driver.FindElement(searchBox); } public IWebElement getSearchButton() { return driver.FindElement(searchButton); } public HomePage(IWebDriver driver) { this.driver = driver; } } }