You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot集成Selenium时WebDriver单测后自动quit()致后续用例报错

问题原因

ChromeDriver的父类RemoteWebDriver实现了AutoCloseable接口,Spring默认会在容器销毁该Bean时自动调用其close()/quit()方法释放资源。
你当前的配置存在两个核心问题:

  1. WebDriverLibrary类没有添加@Configuration注解,Spring无法正确将其识别为配置类,WebDriver Bean的单例生命周期不生效,可能出现重复创建实例的问题。
  2. 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 05:01:03