如何为EmployeeDaoImpl实现JdbcTemplate与RowMapper的Mock并设置ResultSet模拟数据
实现方案(基于Mockito框架)
我们可以通过Mockito拦截JdbcTemplate的query调用,同时模拟ResultSet和触发自定义RowMapper逻辑,完整实现步骤如下:
1. 依赖准备
确保项目引入JUnit 5和Mockito核心依赖,Maven示例配置:
<dependency> <groupId>org.mockito</groupId> <artifactId>mockito-core</artifactId> <version>4.11.0</version> <scope>test</scope> </dependency> <dependency> <groupId>org.mockito</groupId> <artifactId>mockito-junit-jupiter</artifactId> <version>4.11.0</version> <scope>test</scope> </dependency> <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter-api</artifactId> <version>5.9.2</version> <scope>test</scope> </dependency>
2. 测试类基础结构
import org.mockito.junit.jupiter.MockitoExtension; import org.mockito.Mock; import org.mockito.InjectMocks; import org.junit.jupiter.api.extension.ExtendWith; @ExtendWith(MockitoExtension.class) public class EmployeeDaoImplTest { // Mock JdbcTemplate对象 @Mock private JdbcTemplate jdbcTemplate; // 将Mock的JdbcTemplate注入到待测试的Dao类 @InjectMocks private EmployeeDaoImpl employeeDao; }
3. 核心测试逻辑实现
我们用Mockito的Answer机制拦截query调用,既可以验证入参正确性,也能覆盖你写的Lambda形式RowMapper的字段映射逻辑:
import org.junit.jupiter.api.Test; import java.sql.ResultSet; import java.util.Arrays; import java.util.List; import static org.mockito.ArgumentMatchers.*; import static org.mockito.Mockito.*; import static org.junit.jupiter.api.Assertions.*; @Test public void testGetDetailsWithStatusNotNull() { // 1. 构造测试入参 String testSql = "select dept_number, remarks from employee_task where ..."; String countryCode = "CN"; int departmentNumber = 10; Status status = Status.OK; int sectionNumber = 5; int aisle = 3; String zone = "A"; // 2. Mock JdbcTemplate的query方法 when(jdbcTemplate.query(anyString(), any(Object[].class), any(RowMapper.class))).thenAnswer(invocation -> { // 拿到方法调用时传入的自定义RowMapper RowMapper<EmployeeTask> rowMapper = invocation.getArgument(2); // 模拟ResultSet对象 ResultSet mockRs = mock(ResultSet.class); // 模拟第一行数据 when(mockRs.getInt("dept_number")).thenReturn(1001); when(mockRs.getString("remarks")).thenReturn("一号任务"); EmployeeTask task1 = rowMapper.mapRow(mockRs, 1); // 模拟第二行数据 when(mockRs.getInt("dept_number")).thenReturn(1002); when(mockRs.getString("remarks")).thenReturn("二号任务"); EmployeeTask task2 = rowMapper.mapRow(mockRs, 2); // 返回构造好的结果列表 return Arrays.asList(task1, task2); }); // 3. 调用待测试方法 List<EmployeeTask> result = employeeDao.getDetails(testSql, countryCode, departmentNumber, status, sectionNumber, aisle, zone); // 4. 断言结果符合预期 assertEquals(2, result.size()); assertEquals(1001, result.get(0).getDepatmentNumber()); assertEquals("一号任务", result.get(0).getRemartks()); // 也可以验证JdbcTemplate传入的参数是否正确 verify(jdbcTemplate, times(1)).query(eq(testSql), any(Object[].class), any(RowMapper.class)); }
注意事项
- 你提供的原代码存在两处可优化点:一是方法参数未定义
sectionId但直接在参数数组中使用,二是setRemartks大概率是setRemarks的拼写错误,测试前建议先修正。 - 如果你不需要验证RowMapper的映射逻辑,也可以直接让
jdbcTemplate.query返回你预先构造好的List<EmployeeTask>,写法更简单,但无法覆盖Lambda内的逻辑。 - status为空的测试场景只需把入参的status设为null,重复上述逻辑即可。
内容的提问来源于stack exchange,提问作者user15774463
相关产品推荐
相关产品推荐

