使用H2数据库测试JPA Repository的JUnit无数据返回问题排查
解决方案
1. 移除URL中的INIT配置,利用测试环境自动加载脚本
@DataJpaTest默认会自动加载src/test/resources下的data.sql/schema.sql,无需在数据库URL里通过INIT参数指定脚本路径。在src/test/resources/application.properties中配置:
spring.datasource.url=jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1 spring.jpa.hibernate.ddl-auto=create spring.jpa.defer-datasource-initialization=true
spring.jpa.defer-datasource-initialization=true是核心配置:它会让Spring Boot等Hibernate完成表结构创建后,再执行data.sql的插入语句,避免Hibernate的建表操作覆盖已插入的数据。
2. 处理事务回滚的影响
@DataJpaTest默认给每个测试方法开启事务,测试结束自动回滚,但只要data.sql在事务开启前执行,测试方法内就能查询到数据(事务内可见未提交数据)。开启上述defer-datasource-initialization后,数据会在事务启动前插入,无需额外修改事务配置。
3. 对齐枚举类型与JPA实体定义
确保Encouragement实体中的枚举字段使用@Enumerated(EnumType.STRING),和data.sql里的字符串枚举定义匹配:
@Entity public class Encouragement { @Id private Integer id; @Enumerated(EnumType.STRING) private Category category; // 其他字段、构造方法及getter/setter }
如果实体用默认的EnumType.ORDINAL(数字枚举),会和手动创建的字符串枚举类型冲突,导致插入失败(注意查看控制台错误日志)。
4. 简化测试代码
@DataJpaTest已包含@ExtendWith(SpringExtension.class),可去掉冗余注解:
@DataJpaTest class EncouragementRepositoryTest { @Autowired EncouragementRepository repository; @Test public void find_all() { List<Encouragement> list = repository.findAll(); assertEquals(33, list.size()); } }
5. 验证脚本是否被执行
在data.sql开头添加H2支持的打印语句,确认脚本是否被加载:
PRINT '正在执行data.sql...'; drop TYPE Category if exists; drop TYPE Tone if exists; drop TYPE Topic if exists; drop table ENCOURAGEMENT if exists; -- 后续创建表及插入语句
启动测试后查看控制台是否有正在执行data.sql...的输出,以此判断脚本是否被触发。
内容的提问来源于stack exchange,提问作者likejudo
相关产品推荐
相关产品推荐

