springboot+dbunit+h2实现单测

本文介绍了如何在SpringBoot项目中利用Dbunit和H2数据库进行单元测试,以减少对真实数据库的依赖。通过添加相关依赖、配置数据源、编写基类以及初始化数据,实现了单测的隔离执行。测试数据的准备包括DDL脚本的调整、DML脚本的执行,以及特殊场景下使用preparedata目录的XML文件进行初始化。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  在编写单测的过程中,我们应该尽可能的减少单测实例对第三方组件/服务的依赖。本章主要讲解springboot如何通过dbunit+h2实现脱离数据库独立执行单测实例。

1、pom.xml添加依赖,springboot默认已配置相关版本,只需要直接引入依赖即可

    <!-- 单测依赖模块 -->
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-test</artifactId>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>org.dbunit</groupId>
      <artifactId>dbunit</artifactId>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>com.github.springtestdbunit</groupId>
      <artifactId>spring-test-dbunit</artifactId>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>com.h2database</groupId>
      <artifactId>h2</artifactId>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>org.powermock</groupId>
      <artifactId>powermock-module-junit4</artifactId>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>org.powermock</groupId>
      <artifactId>powermock-api-mockito2</artifactId>
      <scope>test</scope>
    </dependency>

2、在test目录新建resources目录,并设置为“Test Resources”,

3、在test/resources目录新建目录:ddl、dml、preparedata;

4、在test/resources目录新建yml文件:application-unit.yml(也可以拷贝工程已使用的配置文件),加入以下配置:

# datasource
spring:
  application:
    name: demo-test
  datasource:
    driver-class-name: org.h2.Driver
    url: jdbc:h2:mem:bone;DB_CLOSE_DELAY=-1;MODE=MYSQL
    username: root
    password: root
    schema: classpath:/ddl/schema.sql
    data: classpath:/dml/*.sql
    initialization-mode: always

注:

  • spring:datasource:schema: 表示启动前执行的脚本,放置建表语句;
  • spring:datasource:data: 放置启动前执行的DML脚本;

5、创建基类:BaseTest(注意:ActiveProfiles的使用)

import com.github.springtestdbunit.DbUnitTestExecutionListener;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.TestExecutionListeners;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.support.DependencyInjectionTestExecutionListener;
import org.springframework.test.context.support.DirtiesContextTestExecutionListener;
import org.springframework.test.context.transaction.TransactionalTestExecutionListener;

/**
 * @author nuoka
 * @version 1.0
 * @date 2019/9/8 14:32
 * <ul>
 *     <li>https://www.jianshu.com/p/bdc0d109e643</li>
 *     <li>@ContextConfiguration: 加载配置</li>
 *     <li>@TestExecutionListeners: 指定在测试类执行之前,可以做的一些动作</li>
 *     <li>@DirtiesContext: 测试类的所有测试执行结束后,该测试的application context会被关闭,同时缓存会清除</li>
 * </ul>
 */
@RunWith(SpringJUnit4ClassRunner.class)
@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD)
@TestExecutionListeners({DependencyInjectionTestExecutionListener.class,
    DirtiesContextTestExecutionListener.class,
    TransactionalTestExecutionListener.class,
    DbUnitTestExecutionListener.class})
@SpringBootTest(classes = DemoTestApplication.class)
@ActiveProfiles(profiles = "unit")
public abstract class BaseTest {

    @Test
    public void name() {
        Assert.assertTrue(Boolean.TRUE);
    }
}

6、单测类继承BaseTest,run test即可。实现原理说透其实是把存储介质由mysql切换到h2,所以原有单测代码不需要做其他改动,唯一要做的就是集成BaseTest。

7、前面的步骤看着都相对的简单,下面开始填坑:

  • ddl.sql的编写非常费劲,博主是把mysql的数据结构全局导出,一点点的调整到完全兼容h2才能完美运行,mysql有很多关键字(comment,等)在h2并没有得到兼容,具体细节建议call百度姐姐,下面是博主的一个建表脚本,可参考使用:
drop table if exists `T_SYS_DICT`;
CREATE TABLE `T_SYS_DICT` (
  `DICT_ID` varchar(32) NOT NULL,
  `DICT_CODE` varchar(32) NOT NULL,
  `DICT_TYPE` varchar(32) NOT NULL,
  `DICT_NAME` varchar(100) NOT NULL,
  `PARENT_DICT_CODE` varchar(100) DEFAULT NULL,
  `SORT_NO` int(4) NOT NULL
  PRIMARY KEY (`DICT_ID`)
) DEFAULT CHARSET=utf8;
  • dml目录主要用来放置初始化的数据(inset 语句),单测启动会自动扫描并执行,这可以省去很多功夫,但数据准备也费劲,而且需要长时间维护,不建议放置太多的测试数据,只需要满足单测执行需求即可;

针对部分特殊的单测,dml初始化的数据无法满足使用,可定义到preparedata目录,原则上应尽可能保证测试数据的纯洁、准确。

<?xml version="1.0" encoding="UTF-8"?>
<dataset>
  <log_info
    id="9999"
    batch_id="A0012345653"
    type="1"
    push_status="0"
    error_log="2021-02-25 13:54:26"
  />
</dataset>

在preparedata目录建立如上的xml文件后,通过@DatabaseSetup引入:

@DatabaseSetup(value = {"classpath:preparedata/LogInfoMapper.xml"}, connection = "datasource", type = DatabaseOperation.INSERT)
@DatabaseTearDown
public class LogInfoMapperTest extends BaseTest {

 经过如上配置,执行单测前会自动加载preparedata目录,来实现对一些特殊数据的初始化;

------------------------------------------------->>到底部了(⊙o⊙)…<<-----------------------------------------------

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值