使用h2database对java关系数据库访问逻辑进行测试

本文围绕Java单元测试展开,介绍了单元测试的Air和BCDE原则。在数据库访问测试方法上,对比了搭建单测环境、mock数据访问层接口和使用内存数据库三种方式,推荐使用h2database。还介绍了h2database的特点、在Spring Boot中的使用、通过web控制台访问方法,以及常见错误处理。

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

1 单元测试的基本原则

  • Air原则:Automatic(自动化)、Independent(独立)、Repeatable(可重复)。即单元测试应该是全自动执行的,不需要依赖人工去交互触发执行、检查。其次为了保持稳定可靠且易维护,单元测试用例之间不能相互调用且执行不受先后次序影响。最后就是可重复执行,通过断言判断,可以重复对测试结果验证。
  • BCDE原则
    • Border:边界测试,包括循环、 特殊取,边界值测试包括循环、 特殊取特殊时间点、数据顺序等。
    • Correct:给出正确的输入,并得到预期结果。
    • Design:与设计文档相结合,来编写单元测试。
    • Error:强制提供错误信息输入(如:非法数据、异常流程业务允许等),并得到预期错误验证结果。

2 数据库访问的测试测试方法

  • 搭建单测环境测试:测试环境专门创建一个单测库,并进行相关配置,最终进行测试。这种方式的优点是减少环境依赖,并对数据进行mock。但也存在缺点,种方式转换为依赖特定的单测库,可能有某些原因库中数据被修改,导致测试用例不稳定。此外依赖外部调用(对远程数据库访问),脱离相关环境,单测无法执行。
  • 直接mock数据访问层接口:这种方式直接通过Mockito框架mock接口,使测试可以保持独立,但Sql逻辑无法得到验证。
  • 使用内存数据库:这种方法避免了对外部环境依赖,使测试独立稳定,但内存数据库和系统中使用的关系数据库存在差异,例如关键字、语法等。这样需要再次解决这些问题。

数据访问层的核心就是sql,因此逻辑正确性也必须验证。通过对比看,第三种方式满足诉求。

3 H2database简介

h2database是一个用Java编写的嵌入式关系型数据库管理系统,可以在内存中运行。h2database支持标准的SQL语法和JDBC API。此外h2database还具备下列特点:

  • 高性能:采用了高效的算法和数据结构,具有出色的性能。
  • 轻量:的代码量非常小,可以很容易地嵌入到应用程序中,同时也支持多种部署方式。
  • 兼容性强:支持标准的SQL语法和JDBC API,同时也支持多种数据库的兼容模式。
  • 可靠性高:采用了事务机制和数据持久化技术,可以保证数据的一致性和可靠性。
  • 使用简介:提供了丰富的文档和示例,可以很容易地上手使用。

4. Spring Boot中使用h2database

添加依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency> 
<dependency>
    <groupId>com.h2database</groupId>
    <artifactId>h2</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
</dependency>

src/test/resources/application.properties文件下增加配置属性

spring.datasource.driver-class-name=org.h2.Driver
spring.datasource.url=jdbc:h2:mem:db;DB_CLOSE_DELAY=-1
spring.datasource.username=sa
spring.datasource.password=sa

此外可以将属性单独配置在一个属性文件中。例如在src/test/resources/persistence-generic-entity.properties文件下单独配置h2db的属性。

jdbc.driverClassName=org.h2.Driver
jdbc.url=jdbc:h2:mem:db;DB_CLOSE_DELAY=-1
jdbc.username=sa
jdbc.password=sa

在单测中写测试,如果我们对h2db使用了单独的测试文件,那么单测中需要通过注解引入配置。
我们先定义配置:

@Configuration
@EnableJpaRepositories(basePackages = "org.baeldung.repository")
@PropertySource("persistence-generic-entity.properties")
@EnableTransactionManagement
public class H2JpaConfig {
    // ...
}

单测中引入配置

@RunWith(SpringRunner.class)
@SpringBootTest(classes = {Application.class, H2JpaConfig.class})
public class SpringBootH2IntegrationTest {
    // ...
}

如果没有单独使用配置文件,那么按如下方式配置即可

@RunWith(SpringRunner.class)
@SpringBootTest(classes = Application.class)
public class SpringBootJPAIntegrationTest {
 
    @Autowired
    private GenericEntityRepository genericEntityRepository;

    @Test
    public void givenGenericEntityRepository_whenSaveAndRetreiveEntity_thenOK() {
    }
}

5.通过web控台访问h2database

在前文介绍的配置文件中增加配置

spring.h2.console.enabled=true

接着启动系统,通过http://localhost:8080/h2-console打开控制台。 8080端口是设置的http端口。
在这里插入图片描述
接着输入前文中配置的用户名密码后就可以进入后台看到数据。
在这里插入图片描述

6 org.h2.jdbc.JdbcSQLException: Syntax error in SQL statement错误处理

遇到这种情况是mysql语法与h2db有差异,此时如果使用idea,可以使用 「MySql To H2」这个插件进行转换,随后就能得到可执行的SQL。
在这里插入图片描述

7 UnboundConfigurationPropertiesException c[1].mapperlocations] were left unbound出错处理

遇到这个问题是配置文件中为了配置多套属性,使用了数组的方式配置

c[1].p1=xxx
c[1].p2=xxx

但在一个属性文件中,这种方式下标从0开始,必须连续。因此调整为c[0].p1。如果后续再有配置,连续配置即可 c[1].p1 ,… c[n].p1 届。

参考

[1].https://www.baeldung.com/spring-testing-separate-data-source
[2].https://www.baeldung.com/spring-boot-h2-database

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值