Selenium C#中DefaultWait的IgnoreExceptionTypes失效问题求助
问题:使用DefaultWait等待元素可点击时,TargetInvocationException未被忽略导致提前失败
我在等待WebElement可点击时使用了DefaultWait,尽管已经把TargetInvocationException加入忽略异常列表,但测试还是在超时时间到之前就因为这个异常失败了,这和预期不符。相关代码如下:
public static void WaitAndClick(this IWebDriver driver, IWebElement webelement) { DefaultWait<IWebDriver> fluentWait = new DefaultWait<IWebDriver>(driver) { Timeout = TimeSpan.FromSeconds(Configuration.WaitTime.TotalSeconds), PollingInterval = TimeSpan.FromMilliseconds(500) }; fluentWait.IgnoreExceptionTypes(typeof(TargetInvocationException),typeof(NoSuchElementException),typeof(InvalidOperationException)); fluentWait.Until(ExpectedConditions.ElementToBeClickable(webelement)); webelement.Click(); }
问题分析与解决方案
嘿,这个问题我之前也踩过坑!核心原因是**ExpectedConditions.ElementToBeClickable在接收已获取的IWebElement实例时,会把内部抛出的异常包装成TargetInvocationException**,而DefaultWait的IgnoreExceptionTypes只能忽略直接抛出的异常类型,没法识别被嵌套在内部的那个异常,所以你的忽略设置根本没生效。
给你两个靠谱的解决办法:
- 办法一:自定义等待条件,自己处理异常
别用现成的ExpectedConditions了,自己写个简单的等待逻辑,直接在条件里捕获所有你想忽略的异常,返回false让等待继续。这样就绕开了异常被包装的问题,示例代码如下:
public static void WaitAndClick(this IWebDriver driver, IWebElement webelement) { DefaultWait<IWebDriver> fluentWait = new DefaultWait<IWebDriver>(driver) { Timeout = TimeSpan.FromSeconds(Configuration.WaitTime.TotalSeconds), PollingInterval = TimeSpan.FromMilliseconds(500) }; // 这里不用在Wait里加忽略列表,自定义条件里直接处理 fluentWait.Until(_ => { try { // 检查元素是否可见且可点击 return webelement.Displayed && webelement.Enabled; } catch (TargetInvocationException) { return false; } catch (NoSuchElementException) { return false; } catch (InvalidOperationException) { return false; } }); webelement.Click(); }
- 办法二:传入定位器而非已获取的元素
如果你把参数改成By定位器,而不是提前获取的IWebElement,ElementToBeClickable会每次自动重新查找元素,这时候抛出的异常都是直接类型(比如NoSuchElementException),不会被包装,你的忽略列表就能正常工作了。修改后的代码:
public static void WaitAndClick(this IWebDriver driver, By locator) { DefaultWait<IWebDriver> fluentWait = new DefaultWait<IWebDriver>(driver) { Timeout = TimeSpan.FromSeconds(Configuration.WaitTime.TotalSeconds), PollingInterval = TimeSpan.FromMilliseconds(500) }; fluentWait.IgnoreExceptionTypes(typeof(NoSuchElementException),typeof(InvalidOperationException)); var webelement = fluentWait.Until(ExpectedConditions.ElementToBeClickable(locator)); webelement.Click(); }
另外给你个小提示:尽量避免提前获取IWebElement,因为页面刷新或者元素重渲染后,之前获取的元素会变成过时元素(StaleElementReferenceException),操作它会抛出各种异常。用定位器每次查找的方式更可靠,也能减少这类问题的发生。
内容的提问来源于stack exchange,提问作者Frank
相关产品推荐
相关产品推荐

