Selenium WebDriver中driver.wait(0)触发IllegalMonitorStateException问题
解决Selenium中
driver.wait(0)触发的IllegalMonitorStateException异常 在使用Selenium WebDriver执行测试时,代码中的driver.wait(0)语句触发了java.lang.IllegalMonitorStateException异常,原本期望通过该语句等待弹窗加载,确保后续操作正常执行。
堆栈跟踪信息
java.lang.IllegalMonitorStateException at java.lang.Object.wait(Native Method) at Test.MounaTest.test(MounaTest.java:61) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:725) at org.junit.jupiter.engine.execution.MethodInvocation.proceed(MethodInvocation.java:60) at org.junit.jupiter.engine.execution.InvocationInterceptorChain$ValidatingInvocation.proceed(InvocationInterceptorChain.java:131) at org.junit.jupiter.engine.extension.TimeoutExtension.intercept(TimeoutExtension.java:149) at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestableMethod(TimeoutExtension.java:140) at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestMethod(TimeoutExtension.java:84) at org.junit.jupiter.engine.execution.ExecutableInvoker$ReflectiveInterceptorCall.lambda$ofVoidMethod$0(ExecutableInvoker.java:115) at org.junit.jupiter.engine.execution.ExecutableInvoker.lambda$invoke$0(ExecutableInvoker.java:105) at org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptedInvocation.proceed(InvocationInterceptorChain.java:106) at org.junit.jupiter.engine.execution.InvocationInterceptorChain.proceed(InvocationInterceptorChain.java:64) at org.junit.jupiter.engine.execution.InvocationInterceptorChain.chainAndInvoke(InvocationInterceptorChain.java:45) at org.junit.jupiter.engine.execution.InvocationInterceptorChain.invoke(InvocationInterceptorChain.java:37) at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:104) at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:98) at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$7(TestMethodTestDescriptor.java:214) at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:210) at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:135) at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:66) at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:151) at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141) at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137) at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139) at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138) at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95) at java.util.ArrayList.forEach(ArrayList.java:1259) at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41) at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155) at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141) at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137) at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139) at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138) at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95) at java.util.ArrayList.forEach(ArrayList.java:1259) at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41) at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155) at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141) at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137) at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139) at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138) at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95) at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:35) at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57) at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:54) at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:107) at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:88) at org.junit.platform.launcher.core.EngineExecutionOrchestrator.lambda$execute$0(EngineExecutionOrchestrator.java:54) at org.junit.platform.launcher.core.EngineExecutionOrchestrator.withInterceptedStreams(EngineExecutionOrchestrator.java:67) at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:52) at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:114) at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:95) at org.junit.platform.launcher.core.DefaultLauncherSession$DelegatingLauncher.execute(DefaultLauncherSession.java:91) at org.junit.platform.launcher.core.SessionPerRequestLauncher.execute(SessionPerRequestLauncher.java:60) at org.eclipse.jdt.internal.junit5.runner.JUnit5TestReference.run(JUnit5TestReference.java:98) at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:40) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:529) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:756) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:452) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:210)
原测试代码
package Test; // Generated by Selenium IDE import org.junit.Before; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.After; import static org.junit.Assert.*; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.core.IsNot.not; import org.openqa.selenium.By; import org.openqa.selenium.WebDriver; import org.openqa.selenium.firefox.FirefoxDriver; import org.openqa.selenium.chrome.ChromeDriver; import org.openqa.selenium.remote.RemoteWebDriver; import org.openqa.selenium.remote.DesiredCapabilities; import org.openqa.selenium.Dimension; import org.openqa.selenium.WebElement; import org.openqa.selenium.interactions.Actions; import org.openqa.selenium.support.ui.ExpectedConditions; import org.openqa.selenium.support.ui.WebDriverWait; import org.openqa.selenium.JavascriptExecutor; import org.openqa.selenium.Alert; import org.openqa.selenium.Keys; import java.util.*; import java.net.MalformedURLException; import java.net.URL; public class MounaTest { private static WebDriver driver; private Map<String, Object> vars; JavascriptExecutor js; @BeforeEach public void setUp() { driver = new ChromeDriver(); js = (JavascriptExecutor) driver; vars = new HashMap<String, Object>(); } @AfterAll public static void tearDown() { driver.quit(); } public String waitForWindow(int timeout) { try { Thread.sleep(timeout); } catch (InterruptedException e) { e.printStackTrace(); } Set<String> whNow = driver.getWindowHandles(); Set<String> whThen = (Set<String>) vars.get("window_handles"); if (whNow.size() > whThen.size()) { whNow.removeAll(whThen); } return whNow.iterator().next(); } @Test public void test() throws InterruptedException { driver.get("https://tinder.com/"); System.out.println("MOUNA CAMELIA"); driver.manage().window().setSize(new Dimension(1552, 840)); driver.wait(0); driver.findElement(By.cssSelector(".Miw\\(120px\\) .l17p5q9z")).click(); driver.switchTo().frame(0); vars.put("window_handles", driver.getWindowHandles()); driver.findElement(By.cssSelector(".ssJRIf")).click(); vars.put("win8338", waitForWindow(2000)); vars.put("root", driver.getWindowHandle()); driver.switchTo().window(vars.get("win8338").toString()); driver.findElement(By.cssSelector(".fFW7wc-ibnC6b-r4m2rf:nth-child(4) > .fFW7wc-ibnC6b-ssJRIf")).click(); driver.close(); driver.switchTo().window(vars.get("root").toString()); { WebElement element = driver.findElement(By.linkText("Terms")); Actions builder = new Actions(driver); builder.moveToElement(element).perform(); } driver.findElement(By.cssSelector(".Mx\\(a\\):nth-child(4) path")).click(); driver.findElement(By.cssSelector(".Sq\\(28px\\) > path")).click();} }
异常原因分析
driver.wait()是JavaObject类的原生方法,调用前必须通过synchronized块获取driver对象的监视器锁,否则会直接抛出IllegalMonitorStateException。- 这种方式完全不符合Selenium的等待规范,
Object.wait()无法感知页面元素或弹窗的加载状态,根本达不到等待的目的。
解决方案
使用Selenium官方推荐的显式等待(WebDriverWait结合ExpectedConditions),它会主动轮询页面,直到目标元素满足指定条件(比如可点击、可见),相比硬等待更高效稳定。
修改后的代码
将原代码中的driver.wait(0)替换为以下显式等待逻辑:
@Test public void test() throws InterruptedException { driver.get("https://tinder.com/"); System.out.println("MOUNA CAMELIA"); driver.manage().window().setSize(new Dimension(1552, 840)); // 替换driver.wait(0)为显式等待,等待目标按钮可点击,超时时间设为10秒 WebDriverWait wait = new WebDriverWait(driver, 10); wait.until(ExpectedConditions.elementToBeClickable(By.cssSelector(".Miw\\(120px\\) .l17p5q9z"))); driver.findElement(By.cssSelector(".Miw\\(120px\\) .l17p5q9z")).click(); driver.switchTo().frame(0); vars.put("window_handles", driver.getWindowHandles()); driver.findElement(By.cssSelector(".ssJRIf")).click(); vars.put("win8338", waitForWindow(2000)); vars.put("root", driver.getWindowHandle()); driver.switchTo().window(vars.get("win8338").toString()); driver.findElement(By.cssSelector(".fFW7wc-ibnC6b-r4m2rf:nth-child(4) > .fFW7wc-ibnC6b-ssJRIf")).click(); driver.close(); driver.switchTo().window(vars.get("root").toString()); { WebElement element = driver.findElement(By.linkText("Terms")); Actions builder = new Actions(driver); builder.moveToElement(element).perform(); } driver.findElement(By.cssSelector(".Mx\\(a\\):nth-child(4) path")).click(); driver.findElement(By.cssSelector(".Sq\\(28px\\) > path")).click(); }
额外优化建议
- 原代码中的
waitForWindow方法使用Thread.sleep()属于硬等待,也可以替换为基于窗口句柄变化的显式等待,进一步提升测试稳定性。 - 尽量避免直接使用索引切换frame(
driver.switchTo().frame(0)),建议通过元素定位切换,避免页面结构变化导致测试失败。
内容的提问来源于stack exchange,提问作者منى
相关产品推荐
相关产品推荐

