1. 概述
本教程将创建一个使用内存数据库进行测试的Spring应用。
在标准环境下,应用会配置独立的MySQL数据库,这需要安装运行MySQL服务器,并预先创建好用户和数据库。
为了简化测试流程,我们将跳过MySQL的额外配置,改用H2内存数据库运行JUnit测试。
2. Maven依赖
开发时需要以下依赖:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>6.0.6</version>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-jpa</artifactId>
<version>3.1.0</version>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>2.1.214</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>6.4.2.Final</version>
</dependency>
最新版依赖可从Maven中央仓库下载:
3. 数据模型与仓库
创建一个简单的Student实体类:
@Entity
public class Student {
@Id
private long id;
private String name;
// 标准构造器、getter/setter
}
接着创建基于Spring Data JPA的仓库接口:
public interface StudentRepository extends JpaRepository<Student, Long> {
}
这样Spring就能自动生成Student对象的操作支持。
4. 分离属性源
为区分标准模式和测试模式的数据库配置,我们可以根据应用运行模式从不同位置读取数据库属性文件。
标准模式下属性文件位于src/main/resources,测试模式下则使用src/test/resources的同名文件。
测试运行时,应用会优先查找src/test/resources下的文件。如果未找到,则使用src/main/resources下的文件。如果测试路径下存在同名文件,则会覆盖主路径下的配置。
4.1. 定义属性文件
在src/main/resources创建persistence-student.properties,配置MySQL数据源:
jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/myDb
jdbc.user=tutorialuser
jdbc.pass=tutorialpass
hibernate.dialect=org.hibernate.dialect.MySQLDialect
hibernate.hbm2ddl.auto=create-drop
使用上述配置需要预先创建myDb数据库和tutorialuser/tutorialpass用户。
为使用内存数据库测试,在src/test/resources创建同名文件,配置H2数据库:
jdbc.driverClassName=org.h2.Driver
jdbc.url=jdbc:h2:mem:myDb;DB_CLOSE_DELAY=-1;NON_KEYWORDS=KEY,VALUE
hibernate.dialect=org.hibernate.dialect.H2Dialect
hibernate.hbm2ddl.auto=create
我们配置了H2数据库运行在内存中,自动创建表结构,并在JVM退出时关闭并销毁数据库。
4.2. JPA配置
创建*@Configuration类,加载persistence-student.properties*属性文件,并创建数据源:
@Configuration
@EnableJpaRepositories(basePackages = "com.baeldung.persistence.dao")
@PropertySource("persistence-student.properties")
@EnableTransactionManagement
public class StudentJpaConfig {
@Autowired
private Environment env;
@Bean
public DataSource dataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(env.getProperty("jdbc.driverClassName"));
dataSource.setUrl(env.getProperty("jdbc.url"));
dataSource.setUsername(env.getProperty("jdbc.user"));
dataSource.setPassword(env.getProperty("jdbc.pass"));
return dataSource;
}
// 配置entityManagerFactory
// 配置transactionManager
// 配置额外Hibernate属性
}
5. 创建JUnit测试
基于上述配置编写JUnit测试,使用StudentRepository保存和检索Student实体:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(
classes = { StudentJpaConfig.class },
loader = AnnotationConfigContextLoader.class)
@Transactional
public class InMemoryDBTest {
@Resource
private StudentRepository studentRepository;
@Test
public void givenStudent_whenSave_thenGetOk() {
Student student = new Student(1, "john");
studentRepository.save(student);
Student student2 = studentRepository.findOne(1);
assertEquals("john", student2.getName());
}
}
测试将完全自包含运行——创建内存H2数据库,执行操作,最后关闭连接并销毁数据库,日志如下:
INFO: HHH000400: Using dialect: org.hibernate.dialect.H2Dialect
Hibernate: drop table Student if exists
Hibernate: create table Student (id bigint not null, name varchar(255), primary key (id))
Mar 24, 2017 12:41:51 PM org.hibernate.tool.schema.internal.SchemaCreatorImpl applyImportSources
INFO: HHH000476: Executing import script 'org.hibernate.tool.schema.internal.exec.ScriptSourceInputNonExistentImpl@1b8f9e2'
Hibernate: select student0_.id as id1_0_0_, student0_.name as name2_0_0_ from Student student0_ where student0_.id=?
Hibernate: drop table Student if exists
6. 总结
本示例展示了如何使用内存数据库运行自包含测试。
完整源码可在GitHub获取。
✅ 关键优势:
- 无需外部数据库依赖
- 测试执行快速
- 自动清理测试数据
⚠️ 注意:
- 确保测试路径属性文件覆盖主路径配置
- 生产环境仍需使用真实数据库