Spring 集成嵌入式数据库方便单元测试
Posted carl-zhao
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring 集成嵌入式数据库方便单元测试相关的知识,希望对你有一定的参考价值。
org.springframework.jdbc.datasource.embedded
包提供了对嵌入式 Java 数据库引擎的支持。本机提供了对HSQL 、H2 和 Derby 的支持。还可以使用可扩展API插入新的嵌入式数据库类型和 DataSource 实现。
1、为什么要使用嵌入式数据库?
嵌入式数据库在项目的开发阶段非常有用,因为它具有轻量级的特性。优点包括易于配置、快速启动时间、可测试性以及在开发期间快速演变SQL的能力。
2、使用Spring XML创建嵌入式数据库
如果你想在 Spring ApplicationContext
中将一个嵌入式数据库实例作为 bean 公开,在 spring--jdbc
命名空间中使用 embedded-database
标签:
<jdbc:embedded-database id="dataSource" generate-name="true">
<jdbc:script location="classpath:schema.sql"/>
<jdbc:script location="classpath:test-data.sql"/>
</jdbc:embedded-database>
前面的配置创建了一个嵌入的 HSQL 数据库,其中填充了来自 schema.sql
和 test-data.sql
类路径根目录中的 SQL 资源。此外,作为一种最佳实践,将为嵌入式数据库分配一个惟一生成的名称。嵌入式数据库作为javax.sql.DataSource
类型的 bean 提供给 Spring 容器,然后可以根据需要将其注入到数据访问对象中。
3、以编程方式创建嵌入式数据库
EmbeddedDatabaseBuilder
类为以编程方式构造嵌入式数据库提供了一个流畅的 API。当您需要在独立环境中或在独立集成测试中创建嵌入式数据库时(如以下示例所示),可以使用此方法。
EmbeddedDatabase db = new EmbeddedDatabaseBuilder()
.generateUniqueName(true)
.setType(H2)
.setScriptEncoding("UTF-8")
.ignoreFailedDrops(true)
.addScript("schema.sql")
.addScripts("user_data.sql", "country_data.sql")
.build();
// perform actions against the db (EmbeddedDatabase extends javax.sql.DataSource)
db.shutdown()
关于所有支持选项的详细信息,请咨询 Javadoc for EmbeddedDatabaseBuilder
。
EmbeddedDatabaseBuilder
还可以使用 Java Config 创建一个嵌入式数据库,如下面的例子所示。
@Configuration
public class DataSourceConfig
@Bean
public DataSource dataSource()
return new EmbeddedDatabaseBuilder()
.generateUniqueName(true)
.setType(H2)
.setScriptEncoding("UTF-8")
.ignoreFailedDrops(true)
.addScript("schema.sql")
.addScripts("user_data.sql", "country_data.sql")
.build();
4、选择嵌入式数据库类型
4.1 使用HSQL
Spring支持 HSQL 1.8.0 及以上版本。如果没有显式指定类型,HSQL 是默认的嵌入式数据库。要显式地指定 HSQL
,请将 embedded-database
标记的 type
属性设置为 ```HSQL。如果你使用的是构建器 API,调用
setType(EmbeddedDatabaseType)方法与
EmbeddedDatabaseType.HSQL``。
4.2 使用H2
Spring还支持 H2 数据库。要启用 H2,请将 embedded-database
标记的 type
属性设置为 H2。如果你使用的是构建器API,调用 setType(EmbeddedDatabaseType)
方法与 EmbeddedDatabaseType.H2
。
4.3 使用Derby
Spring 还支持 Apache Derby 10.5 及以上版本。要启用 Derby
,请将 embedded-database
标记的 type
属性设置为 Derby
。如果您正在使用构建器 API,使用EmbeddedDatabaseType.DERBY
调用 setType(EmbeddedDatabaseType)
方法。
5、使用嵌入式数据库测试数据访问逻辑
嵌入式数据库为测试数据访问代码提供了一种轻量级的方法。下面是一个使用嵌入式数据库的数据访问集成测试模板。当嵌入式数据库不需要跨测试类重用时,使用这样的模板对于一次性使用非常有用。然而,如果您希望创建一个在测试套件中共享的嵌入式数据库,请考虑使用 Spring TestContext 框架,并将嵌入式数据库配置为 Spring ApplicationContext
中的 bean
public class DataAccessIntegrationTestTemplate
private EmbeddedDatabase db;
@Before
public void setUp()
// creates an HSQL in-memory database populated from default scripts
// classpath:schema.sql and classpath:data.sql
db = new EmbeddedDatabaseBuilder()
.generateUniqueName(true)
.addDefaultScripts()
.build();
@Test
public void testDataAccess()
JdbcTemplate template = new JdbcTemplate(db);
template.query( /* ... */ );
@After
public void tearDown()
db.shutdown();
6、为嵌入式数据库生成唯一的名称
如果测试套件无意中试图重新创建相同数据库的其他实例,开发团队经常会遇到嵌入式数据库的错误。如果 XML 配置文件或 @Configuration
类负责创建嵌入式数据库,然后在相同测试套件(即在相同的 JVM 流程中)中的多个测试场景中重用相应的配置,那么这种情况会非常容易发生——例如,针对嵌入式数据库的集成测试,其ApplicationContext
配置只与激活的 bean 定义概要文件有关。
这种错误的根本原因是 Spring 的 EmbeddedDatabaseFactory
(由 <jdbc:embedded-database>
XML 命名空间元素和 Java 配置的 EmbeddedDatabaseBuilder
内部使用)将设置嵌入式数据库的名称为 “testdb”
,如果没有另外指定。对于 <jdbc:embedded-database>
的情况,嵌入式数据库通常被分配一个与 bean 的 id
相等的名称(例如,通常类似于 “dataSource”
)。因此,后续创建嵌入式数据库的尝试不会产生新的数据库。相反,将重用相同的 JDBC 连接 URL,并且尝试创建新的嵌入式数据库实际上会指向从相同配置创建的现有嵌入式数据库。
为了解决这个常见问题,Spring Framework 4.2 提供了为嵌入式数据库生成唯一名称的支持。要启用生成的名称,请使用以下选项之一。
EmbeddedDatabaseFactory.setGenerateUniqueDatabaseName()
EmbeddedDatabaseBuilder.generateUniqueName()
<jdbc:embedded-database generate-name="true" … >
7、扩展嵌入式数据库支持
可以通过两种方式扩展 Spring JDBC 嵌入式数据库支持:
- 实现
EmbeddedDatabaseConfigurer
来支持一种新的嵌入式数据库类型。 - 实现
DataSourceFactory
以支持新的DataSource
实现,例如用于管理嵌入式数据库连接的连接池。
我们鼓励您通过 jira.spring.io 向 Spring 社区贡献扩展。
以上是关于Spring 集成嵌入式数据库方便单元测试的主要内容,如果未能解决你的问题,请参考以下文章