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

多表场景下如何用H2数据库、模拟JDBC Template编写DAO类JUnit测试用例

多DAO多表场景下H2 + JdbcTemplate单元测试适配方案

你可以通过抽取公共逻辑、分层管理SQL脚本的方式,把单DAO的测试逻辑复用至全量DAO测试场景,具体实现步骤如下:

1. 抽取公共基础测试父类

把H2数据源初始化、公共脚本加载、DAO依赖注入的通用逻辑全部抽到父类中,避免每个DAO测试重复编写相同代码:

// 基础DAO测试父类
public class BaseDaoTest {
    protected DataSource dataSource;
    protected JdbcTemplate jdbcTemplate;

    // 每个测试方法执行前初始化H2内存库
    @Before
    public void initH2DataSource() {
        EmbeddedDatabaseBuilder dbBuilder = new EmbeddedDatabaseBuilder()
                .setType(EmbeddedDatabaseType.H2)
                // 配置H2兼容模式,适配生产库语法(比如MySQL/PostgreSQL)
                .setName("testdb;MODE=MySQL;DATABASE_TO_LOWER=TRUE;CASE_INSENSITIVE_IDENTIFIERS=TRUE")
                // 加载全量公共建表脚本(比如全局字典表、配置表等所有DAO都依赖的表)
                .addScript("classpath:jdbc/common-schema.sql");
        
        // 可根据测试场景动态添加额外脚本,子类可以覆写这个方法加自己需要的表脚本
        addCustomScripts(dbBuilder);
        
        dataSource = dbBuilder.build();
        jdbcTemplate = new JdbcTemplate(dataSource);
    }

    // 子类扩展点:添加当前DAO测试需要的业务表脚本、测试数据脚本
    protected void addCustomScripts(EmbeddedDatabaseBuilder dbBuilder) {
    }

    // 每个测试方法执行后销毁H2库,保证测试数据隔离
    @After
    public void destroyH2DataSource() {
        if (dataSource instanceof EmbeddedDatabase) {
            ((EmbeddedDatabase) dataSource).shutdown();
        }
    }
}

2. 分层管理SQL脚本

如果表数量较多,不要把所有建表语句都放在同一个schema.sql里,按业务模块拆分脚本:

  • 公共脚本:存放在classpath:jdbc/common/目录下,放所有DAO都依赖的公共表结构、基础数据
  • 业务模块脚本:按业务域拆分,比如classpath:jdbc/user/放用户相关表脚本,classpath:jdbc/order/放订单相关表脚本,每个模块下分开存放schema.sql(建表语句)和test-data.sql(测试数据)
  • 按需加载:测试对应DAO的时候,只加载依赖的模块脚本,不需要全量加载所有表,大幅提升测试启动速度

3. 单DAO测试实现

各个DAO的测试类只要继承基础父类,按需加载对应业务脚本即可,不需要再重复写H2初始化逻辑:

public class EmployeeDAOTest extends BaseDaoTest {
    private EmployeeDAO employeeDAO;

    // 扩展父类方法,加载员工模块的表结构和测试数据
    @Override
    protected void addCustomScripts(EmbeddedDatabaseBuilder dbBuilder) {
        dbBuilder.addScript("classpath:jdbc/employee/schema.sql")
                .addScript("classpath:jdbc/employee/test-data.sql");
    }

    @Before
    public void initDao() {
        employeeDAO = new EmployeeDAO();
        // 如果DAO依赖DataSource直接注入
        employeeDAO.setDataSource(dataSource);
        // 如果DAO依赖JdbcTemplate就注入JdbcTemplate
        // employeeDAO.setJdbcTemplate(jdbcTemplate);
    }

    @Test
    public void whenQueryEmployeeCount_thenReturnCorrectValue() {
        assertEquals(4, employeeDAO.getCountOfEmployees());
    }

    // 其他DAO方法测试直接写即可
}

4. 大量表场景的优化方案

如果表数量超过百级,全量加载脚本速度慢,可以做以下优化:

  • 按需加载依赖表:测试某个DAO时只加载它操作的相关表,不要加载无关业务域的表
  • 复用H2实例:把H2的初始化逻辑从@Before改成@BeforeClass,整个测试类只初始化一次数据源,测试方法之间通过清理数据脚本保证隔离,不用每次重建库
  • 开启H2缓存:在H2连接参数中添加;CACHE_SIZE=10000,提升SQL执行速度

注意事项

  • 如果生产库用了特殊语法(比如MySQL的ON DUPLICATE KEY UPDATE、PostgreSQL的COPY语法),需要提前测试H2的兼容情况,少量不兼容的SQL可以单独写H2适配版本的脚本
  • 可以配合@Transactional注解实现测试数据自动回滚,不用手动编写清理数据的脚本

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 18:45:04