Spring Boot集成Selenium时WebDriver单测后自动quit()致后续用例报错
问题原因
ChromeDriver的父类RemoteWebDriver实现了AutoCloseable接口,Spring默认会在容器销毁该Bean时自动调用其close()/quit()方法释放资源。
你当前的配置存在两个核心问题:
WebDriverLibrary类没有添加@Configuration注解,Spring无法正确将其识别为配置类,WebDriver Bean的单例生命周期不生效,可能出现重复创建实例的问题。- Spring Test默认的测试上下文生命周期为测试类级别,如果你混用了TestNG和Spring Boot Test默认带的JUnit5运行器,会导致测试方法执行完就触发上下文销毁,自动调用WebDriver的
quit()方法,后续测试拿到的就是已经失效的会话实例,抛出Session ID is null错误。
解决方案
不需要放弃页面对象的依赖注入,按照以下步骤调整配置即可:
第一步:修正WebDriver配置类
给配置类加上@Configuration注解,同时显式指定Bean的销毁方法为空,禁止Spring自动调用quit(),统一在测试套件完成后手动释放资源:
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import io.github.bonigarcia.wdm.WebDriverManager; import org.openqa.selenium.WebDriver; import org.openqa.selenium.chrome.ChromeDriver; import java.util.concurrent.TimeUnit; @Configuration public class WebDriverLibrary { // 关键:destroyMethod设为空字符串,关闭Spring自动销毁逻辑 @Bean(destroyMethod = "") public WebDriver getChromeDriver() { WebDriverManager.chromedriver().setup(); ChromeDriver driver = new ChromeDriver(); // 把原BasePage中PostConstruct里的驱动全局配置移到这里统一初始化 driver.manage().timeouts().pageLoadTimeout(5, TimeUnit.SECONDS); return driver; } }
第二步:删除BasePage中重复的驱动初始化配置
原BasePage里的@PostConstruct方法中重复设置了pageLoadTimeout,直接删掉该部分逻辑,只保留页面对象初始化即可:
public abstract class BasePage { @Autowired private WebDriver driver; @Autowired protected Properties properties; @PostConstruct public void initDriver() { // 删掉原来的pageLoadTimeout设置,已经在Bean初始化时统一配置 PageFactory.initElements(driver, this); } // 其余原有方法保持不变 }
第三步:添加全局测试生命周期钩子,统一关闭驱动
新增一个测试生命周期管理类,在整个测试套件执行完成后手动调用quit()关闭浏览器,避免资源泄漏:
import org.openqa.selenium.WebDriver; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.testng.annotations.AfterSuite; @Component public class TestLifecycleConfig { @Autowired private WebDriver driver; // alwaysRun保证哪怕测试用例失败也会执行关闭逻辑 @AfterSuite(alwaysRun = true) public void cleanUpDriver() { driver.quit(); } }
第四步(可选):统一测试框架,避免生命周期冲突
你当前的依赖里同时引入了TestNG和JUnit Jupiter(spring-boot-starter-test默认集成JUnit5),两个测试框架的生命周期管理逻辑不兼容,建议保留一个即可。如果继续用TestNG,可以把JUnit相关依赖排除,避免上下文生命周期混乱。
其他可选方案
如果你希望每个测试方法都用独立的浏览器会话,不需要跨用例复用WebDriver,可以将WebDriver的作用域调整为测试方法级别,每个用例执行前创建新驱动,执行完主动销毁,也能避免会话失效问题。
内容的提问来源于stack exchange,提问作者disco.dan.silver
相关产品推荐
相关产品推荐

