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