测试含数据库操作的业务代码需区分单元测试(用Mock隔离数据库,验证逻辑)和集成测试(连真实库验证SQL、事务等),并专项测试连接池,注意配置、时区、权限及时间断言等细节。

直接对含数据库操作的业务代码做测试,关键在于分清测试类型和目标:单元测试要隔离数据库,集成测试则必须连库。不能混用策略,否则要么测不真实,要么太慢太脆。
单元测试:用 Mock 隔离数据库依赖
适用于验证 Service 层逻辑,比如“用户注册时邮箱是否已存在”这类判断,不关心数据真存没存进库。
- 用 @Mock 模拟 Mapper 或 DAO 接口,比如
UserMapper - 用 @InjectMocks 注入待测 Service,它会自动把 Mock 对象塞进去
- 在
@Test方法里调用业务方法,然后用verify()检查是否调用了预期的 DAO 方法,或用when(...).thenReturn(...)控制返回值 - 不需要启动数据库,也不需要配置数据源,运行快、稳定性高
集成测试:真实连接数据库跑 CRUD
用于验证 SQL 是否写对、事务是否生效、MyBatis 映射是否准确等,必须走真实数据库。
- 使用 @SpringBootTest + @AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE),让 Spring Boot 加载你配置的真实数据源(如 PostgreSQL、MySQL)
- 测试前用 @Sql 执行初始化脚本(如插入测试数据),或用 Flyway/Liquibase 管理测试库结构
- 推荐用内存数据库(如 H2)做轻量集成测试;若必须测生产库(如 OceanBase、PostgreSQL),需确保测试环境独立、数据可重置
- 注意清理:用 @AfterEach 清空表,或开启事务并在方法结束时回滚(@Transactional)
连接池与工具类的专项测试
像 Druid、HikariCP 这类连接池,本身不是业务逻辑,但直接影响稳定性,需要单独验证。
立即学习“Java免费学习笔记(深入)”;
- 写一个简单
main或@Test方法,调用DruidUtils.getConnection()获取连接,执行SELECT 1,确认不抛异常 - 检查连接是否能正常关闭(避免泄露),可配合日志或连接池监控指标(如
getActiveCount())观察 - 不建议在单元测试里测连接池性能,这类验证更适合放在 CI 阶段用 JMeter 或 Gatling 做专项压测
避免踩坑的实操细节
很多测试失败其实和代码无关,而是环境或配置疏忽导致。
- 确保测试用的数据库 URL、用户名、密码在
application-test.yml中正确,且该配置被激活(@ActiveProfiles("test")) - MySQL 8+ 需加
serverTimezone=UTC,PostgreSQL 要确认postgres用户有建表权限 - 不要在测试中手动
new Connection()或拼接 SQL——这绕过了 MyBatis/Spring 的事务管理和连接池,测了也白测 - 涉及时间字段的测试(如
create_time),避免用new Date()断言精确毫秒值,改用范围断言或使用Instant.now().truncatedTo(Seconds)


















