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

如何在不重复JPA配置类的前提下将H2依赖设为test scope?

问题分析

运行mvn clean verify -Denv=dev测试时出现Could not load JDBC driver class [org.h2.Driver]错误,核心原因:

  • 测试阶段会加载主类路径下的PersistenceJpaConfig,该配置读取persistence-dev.properties中的H2驱动配置;
  • 但H2依赖被设置为test scope,主类路径(compile scope)不包含该依赖,导致Spring创建DataSource Bean时无法找到H2驱动类。
解决方案

方案一:用Spring Profiles隔离主环境与测试环境配置

1. 修改主配置类的生效范围

给PersistenceJpaConfig添加@Profile注解,限制它仅在非测试环境生效:

@Configuration
@EnableTransactionManagement
@PropertySource("classpath:persistence-${env:int}.properties")
@EnableJpaRepositories(basePackages = "fr.tristan.demoassurance.infrastructure.repository.mysql")
@Profile("!test") // 仅在非test Profile下激活
@SuppressWarnings("unused")
public class PersistenceJpaConfig {
    // 原有代码保持不变
}

2. 创建测试专用JPA配置类

在测试类路径(src/test/java)下新建测试配置类,仅在test Profile生效:

@Configuration
@EnableTransactionManagement
@PropertySource("classpath:persistence-test.properties")
@EnableJpaRepositories(basePackages = "fr.tristan.demoassurance.infrastructure.repository.mysql")
@Profile("test")
public class TestPersistenceJpaConfig {

    @Bean
    LocalContainerEntityManagerFactoryBean entityManagerFactory(Environment env) {
        final LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
        em.setDataSource(dataSource(env));
        em.setPackagesToScan("fr.tristan.demoassurance.infrastructure.repository.mysql.entity");

        final JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
        em.setJpaVendorAdapter(vendorAdapter);
        em.setJpaProperties(additionalProperties(env));

        return em;
    }

    @Bean
    DataSource dataSource(Environment env) {
        final DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setDriverClassName(Preconditions.checkNotNull(env.getProperty("jdbc.driverClassName")));
        dataSource.setUrl(Preconditions.checkNotNull(env.getProperty("jdbc.url")));
        dataSource.setUsername(Preconditions.checkNotNull(env.getProperty("jdbc.user")));
        dataSource.setPassword(Preconditions.checkNotNull(env.getProperty("jdbc.pass")));

        return dataSource;
    }

    @Bean
    PlatformTransactionManager transactionManager(EntityManagerFactory emf) {
        final JpaTransactionManager transactionManager = new JpaTransactionManager();
        transactionManager.setEntityManagerFactory(emf);
        return transactionManager;
    }

    @Bean
    PersistenceExceptionTranslationPostProcessor exceptionTranslation() {
        return new PersistenceExceptionTranslationPostProcessor();
    }

    final Properties additionalProperties(Environment env) {
        final Properties hibernateProperties = new Properties();
        hibernateProperties.setProperty("hibernate.hbm2ddl.auto", env.getProperty("hibernate.hbm2ddl.auto"));
        hibernateProperties.setProperty("hibernate.hbm2ddl.import_files", env.getProperty("hibernate.hbm2ddl.import_files"));
        hibernateProperties.setProperty("hibernate.dialect", env.getProperty("hibernate.dialect"));
        hibernateProperties.setProperty("hibernate.cache.use_second_level_cache", env.getProperty("hibernate.cache.use_second_level_cache"));
        hibernateProperties.setProperty("hibernate.cache.use_query_cache", env.getProperty("hibernate.cache.use_query_cache"));
        return hibernateProperties;
    }
}

3. 激活测试类的test Profile

@SpringBootTest
@ActiveProfiles("test")
public class DemoAssuranceServiceIntegrationTest {
    // 测试代码
}

4. 新增测试配置文件

在测试资源路径(src/test/resources)下创建persistence-test.properties:

jdbc.driverClassName=org.h2.Driver
jdbc.url=jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1
jdbc.user=sa
jdbc.pass=

hibernate.hbm2ddl.auto=create-drop
hibernate.hbm2ddl.import_files=import-test-data.sql
hibernate.dialect=org.hibernate.dialect.H2Dialect
hibernate.cache.use_second_level_cache=false
hibernate.cache.use_query_cache=false

方案二:在主配置类中动态适配测试环境

无需新增测试配置类,修改主配置类的dataSource方法,根据当前Profile动态切换数据源配置:

@Bean
DataSource dataSource(Environment env) {
    final DriverManagerDataSource dataSource = new DriverManagerDataSource();
    
    // 判断是否为测试环境
    if (env.acceptsProfiles(Profiles.of("test"))) {
        // 测试环境直接使用H2嵌入式数据库配置
        dataSource.setDriverClassName("org.h2.Driver");
        dataSource.setUrl("jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1");
        dataSource.setUsername("sa");
        dataSource.setPassword("");
    } else {
        // 非测试环境读取配置文件中的参数
        dataSource.setDriverClassName(Preconditions.checkNotNull(env.getProperty("jdbc.driverClassName")));
        dataSource.setUrl(Preconditions.checkNotNull(env.getProperty("jdbc.url")));
        dataSource.setUsername(Preconditions.checkNotNull(env.getProperty("jdbc.user")));
        dataSource.setPassword(Preconditions.checkNotNull(env.getProperty("jdbc.pass")));
    }
    
    return dataSource;
}

同时在测试类上添加@ActiveProfiles("test"),测试时自动切换到H2配置。


内容的提问来源于stack exchange,提问作者Tristan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 16:15:11