如何Mock与Service层存在同名方法的DAO层进行测试?
DAO层测试实现方案
核心测试逻辑区分
首先明确和Service层同名方法的测试边界,两者完全不冲突:
- Service层同名方法测试:核心验证业务规则、参数校验、事务、跨组件调用逻辑,测试时通常Mock DAO层返回
- DAO层方法测试:仅验证数据访问逻辑的正确性,不涉及任何业务流程,测试直接和数据库交互
测试环境配置
推荐使用Spring Boot自带的测试注解搭建轻量测试环境,避免加载不必要的Service层Bean:
- 用
@JdbcTest注解标注DAO测试类,该注解会自动配置测试用嵌入式数据源(默认H2)、NamedParameterJdbcTemplate,仅扫描@Repository相关Bean,完全隔离Service层逻辑 - 也可使用Testcontainers启动和生产环境一致的数据库实例,保证测试结果和生产行为完全匹配
测试用例设计
针对你提供的findSomething方法,需要覆盖以下核心场景:
- 正常匹配场景:提前向测试库插入2-3条符合查询条件的
myTable数据,调用方法后校验返回Set的大小、每个MyForm属性和插入数据完全一致 - 无匹配数据场景:仅插入不符合查询条件的数据,校验方法返回空集合而非Null
- 参数绑定正确性场景:重点验证时区转换逻辑,传入带指定时区(如东8区)的
ZonedDateTime参数,校验最终执行的SQL中绑定的时间参数为对应UTC时间,查询结果符合预期 - 去重逻辑校验:插入两条完全相同、会被
MyForm的equals/hashCode判定为重复的数据,校验返回Set的大小为1,验证HashSet去重逻辑正常 - 字段映射校验:插入所有字段均有值的测试数据,校验
MyRowMapper返回的MyForm所有属性和数据库存储值一致,不存在字段漏映射、类型转换错误问题
示例测试代码
// 仅加载Jdbc相关配置,不加载Service层Bean @JdbcTest @Import(DaoImpl.class) class DaoImplTest { @Autowired private Dao dao; @Autowired private JdbcTemplate jdbcTemplate; @Test void findSomething_ShouldReturnMatchingRecords() { // 准备测试数据 ZonedDateTime inputTime = ZonedDateTime.of(2024, 5, 20, 12, 0, 0, 0, ZoneId.of("Asia/Shanghai")); jdbcTemplate.update("INSERT INTO myTable(title, name, mydatetime) VALUES (?, ?, ?)", "测试标题", "测试名称", inputTime.withZoneSameInstant(ZoneId.of("UTC")).toOffsetDateTime()); // 调用DAO方法 Set<MyForm> result = dao.findSomething("测试标题", "测试名称", inputTime); // 校验结果 assertThat(result).hasSize(1); MyForm form = result.iterator().next(); assertThat(form.getTitle()).isEqualTo("测试标题"); assertThat(form.getName()).isEqualTo("测试名称"); // 其他字段校验 } }
内容的提问来源于stack exchange,提问作者patchi
相关产品推荐
相关产品推荐

