You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用Mockito为含RowMapper的JdbcTemplate逻辑编写JUnit测试用例?

用Mockito编写该JdbcTemplate查询逻辑的JUnit测试方法

核心思路

不需要连接真实数据库,只需要模拟JdbcTemplate的调用行为,同时通过参数捕获器验证匿名RowMapper的字段映射逻辑是否符合预期即可。

前置依赖

首先需要引入JUnit、Mockito、spring-jdbc相关的测试依赖,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>

如果使用JUnit4,只需替换对应JUnit版本依赖,核心测试逻辑基本一致。

完整测试用例代码

假设你的查询逻辑封装在EmployeeDao类的queryAllEmployee方法中,测试代码如下:

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

@ExtendWith(MockitoExtension.class)
public class EmployeeDaoTest {

    // 模拟JdbcTemplate实例,不会发起真实数据库请求
    @Mock
    private JdbcTemplate jdbcTemplate;

    // 注入模拟的JdbcTemplate到待测试的Dao类
    @InjectMocks
    private EmployeeDao employeeDao;

    // 定义参数捕获器,用来捕获代码中的匿名RowMapper实例
    @Captor
    private ArgumentCaptor<RowMapper<Employee>> rowMapperCaptor;

    @Test
    public void testQueryAllEmployee() throws SQLException {
        // 1. 预设查询返回的模拟结果
        Employee mockEmployee = new Employee();
        mockEmployee.setId("1001");
        mockEmployee.setName("张三");
        List<Employee> expectedList = List.of(mockEmployee);

        // 2. 定义JdbcTemplate调用的模拟规则,同时匹配SQL语句
        when(jdbcTemplate.query(eq("select * from employee"), any(RowMapper.class)))
                .thenReturn(expectedList);

        // 3. 调用待测试的业务方法
        List<Employee> actualList = employeeDao.queryAllEmployee();

        // 4. 校验返回结果是否符合预期
        assertEquals(1, actualList.size());
        assertEquals("1001", actualList.get(0).getId());
        assertEquals("张三", actualList.get(0).getName());

        // ---- 额外校验匿名RowMapper的映射逻辑是否正确 ----
        // 捕获调用时传入的匿名RowMapper实例
        when(jdbcTemplate.query(eq("select * from employee"), rowMapperCaptor.capture()))
                .thenReturn(expectedList);
        employeeDao.queryAllEmployee();
        RowMapper<Employee> mapper = rowMapperCaptor.getValue();

        // 模拟ResultSet对象,构造测试用的字段值
        ResultSet mockRs = mock(ResultSet.class);
        when(mockRs.getString("ID")).thenReturn("2002");
        when(mockRs.getString("NAME")).thenReturn("李四");

        // 手动调用mapRow方法校验映射结果
        Employee mappedEmp = mapper.mapRow(mockRs, 1);
        assertEquals("2002", mappedEmp.getId());
        assertEquals("李四", mappedEmp.getName());
    }
}

关键逻辑说明

  • 用eq匹配器校验执行的SQL语句是否和预期一致,可提前发现SQL拼写错误
  • 通过ArgumentCaptor捕获匿名RowMapper,不需要将RowMapper抽取为单独的公共类即可测试内部映射逻辑
  • 所有数据库相关对象都是模拟生成,测试执行速度快,不依赖环境可用性

内容的提问来源于stack exchange,提问作者Vinutha

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.24 02:06:05