如何为并行SpringBootTest+Junit-Jupiter测试生成独立@Autowired实例
解决SpringBootTest并行测试中WebDriver实例共享问题
核心原因
Spring默认Bean作用域为单例(Singleton),所有测试方法会复用同一个WebDriver实例,导致并行测试时共用一个浏览器会话。要实现每个测试线程独立拥有浏览器实例,需调整Bean作用域或通过JUnit扩展管理实例生命周期。
方案一:将WebDriver Bean改为线程作用域
1. 注册线程作用域支持
创建配置类,让Spring容器支持线程级Bean作用域:
@Component public class ThreadScopeConfig implements BeanFactoryPostProcessor { @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { beanFactory.registerScope("thread", new SimpleThreadScope()); } }
2. 修改WebDriver Bean的作用域
在WebDriverLibrary中为Bean添加线程作用域注解,确保每个线程获取独立实例:
@Component public class WebDriverLibrary { @Bean @Scope("thread") @RefreshScope @ConditionalOnProperty(name = "default.browser", havingValue = "chrome") public WebDriver getDriver() { WebDriverManager.chromedriver().setup(); ChromeOptions options = new ChromeOptions(); options.addArguments("--remote-allow-origins=*"); return new ChromeDriver(options); } }
3. 开启JUnit并行测试
在src/test/resources/junit-platform.properties中配置并行规则:
junit.jupiter.execution.parallel.enabled=true junit.jupiter.execution.parallel.mode.default=concurrent
方案二:原型作用域+JUnit测试实例生命周期
1. 设置WebDriver为原型作用域
原型作用域会在每次注入时生成新的WebDriver实例:
@Component public class WebDriverLibrary { @Bean @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) @ConditionalOnProperty(name = "default.browser", havingValue = "chrome") public WebDriver getDriver() { WebDriverManager.chromedriver().setup(); ChromeOptions options = new ChromeOptions(); options.addArguments("--remote-allow-origins=*"); return new ChromeDriver(options); } }
2. 配置JUnit测试实例生命周期
在测试类上添加注解,确保每个测试方法生成新的测试实例,从而注入新的WebDriver:
@SpringBootTest @SpringJUnitConfig(WebDriverLibrary.class) @TestInstance(TestInstance.Lifecycle.PER_METHOD) public class AppTestCase { @Autowired public WebDriver driver; @Test public void testYoutube() { driver.get("https://www.youtube.com"); driver.quit(); } @Test public void testGoogle() { driver.get("https://www.google.com"); driver.quit(); } }
注意:原型作用域下Spring不会自动销毁Bean,需手动调用
driver.quit()关闭浏览器,避免资源泄漏。
方案三:自定义JUnit扩展管理WebDriver
通过JUnit扩展完全接管WebDriver的创建与销毁,不依赖Spring Bean管理:
1. 实现JUnit扩展类
public class WebDriverExtension implements BeforeEachCallback, AfterEachCallback { private final ThreadLocal<WebDriver> driverThreadLocal = new ThreadLocal<>(); @Override public void beforeEach(ExtensionContext context) throws Exception { WebDriverManager.chromedriver().setup(); ChromeOptions options = new ChromeOptions(); options.addArguments("--remote-allow-origins=*"); WebDriver driver = new ChromeDriver(options); driverThreadLocal.set(driver); // 将driver注入测试类字段 context.getTestInstance().ifPresent(instance -> { try { Field field = instance.getClass().getDeclaredField("driver"); field.setAccessible(true); field.set(instance, driver); } catch (Exception e) { throw new RuntimeException(e); } }); } @Override public void afterEach(ExtensionContext context) throws Exception { WebDriver driver = driverThreadLocal.get(); if (driver != null) { driver.quit(); driverThreadLocal.remove(); } } }
2. 在测试类中使用扩展
@SpringBootTest @ExtendWith(WebDriverExtension.class) public class AppTestCase { public WebDriver driver; @Test public void testYoutube() { driver.get("https://www.youtube.com"); } @Test public void testGoogle() { driver.get("https://www.google.com"); } }
该方案通过ThreadLocal保证线程隔离,自动在测试前后创建/销毁浏览器,无需手动管理资源。
内容的提问来源于stack exchange,提问作者sritej_kr
相关产品推荐
相关产品推荐

