Spring JdbcTemplate Junit 测试 - ResultSetExtractor/RowMapper

Spring JdbcTemplate Junit 测试覆盖率 - 以 ResultSetExtractor / RowMapper 为例

1、RowMapper Mockito 测试

(1)创建实体类 User

java 复制代码
@Data
public class User {

    private Integer id;

    private String name;

    private String applicant;

    private String address;

    private Boolean flag;
}

(2)JdbcTemplate 业务代码

java 复制代码
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Repository;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;

@Repository
public class InsertGroup {

    @Autowired
    JdbcTemplate jdbcTemplate;

    public List<User> getUsers(String sql, String name, String address) {

        return jdbcTemplate.query(sql, new RowMapper<User>() {
            @Override
            public User mapRow(ResultSet rs, int rowNum) throws SQLException {

                User user = new User();
                user.setId(rs.getInt("ID"));
                user.setName(rs.getString("Name"));
                user.setApplicant(rs.getString("Applicant"));
                user.setAddress(rs.getString("Address"));
                user.setFlag(rs.getBoolean("Flag"));
                return user;
            }
        }, name, address);
    }
}

(3)Junit 测试

java 复制代码
package com.example.dao;

import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.*;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;

@RunWith(SpringJUnit4ClassRunner.class)
public class InsertGroupTest {

    @Mock
    JdbcTemplate jdbcTemplate;

    @InjectMocks
    InsertGroup insertGroup;

    @Before
    public void init() {
        MockitoAnnotations.openMocks(this);
    }


    @Test
    public void test() {

      /**
         * 需要注意的是:invocation.getArgument(1)
         * jdbcTemplate.query() 中 Mock 的参数索引是以0开始的,RowMapper 是第二个元素,因此索引是 1,如果是第三个位置,那么索引是 2,即 invocation.getArgument(2)
         * 同时需要注意的是,jdbcTemplate 中 query 的方法有很多,但是传的参数是不同的,因此 Mock 的参数数量要根据自己实际用到的 query 参数为准
         */
        Mockito.when(jdbcTemplate.query(
                        ArgumentMatchers.anyString(), ArgumentMatchers.any(RowMapper.class), ArgumentMatchers.any()))
                .thenAnswer((invocation) -> {

                    RowMapper<User> rowMapper = (RowMapper<User>) invocation.getArgument(1);
                    ResultSet rs = Mockito.mock(ResultSet.class);

                    // Mock ResultSet to return one rows.
                    // Mockito.when(rs.getInt(ArgumentMatchers.eq("ID"))).thenReturn(506);

                    // Mock ResultSet to return two rows.
                    Mockito.when(rs.getInt(ArgumentMatchers.eq("ID")))
                            .thenReturn(412, 300);
                    Mockito.when(rs.getString(ArgumentMatchers.eq("Name")))
                            .thenReturn("刘亦菲", "刘诗诗");
                    Mockito.when(rs.getBoolean(ArgumentMatchers.eq("Flag")))
                            .thenReturn(true, false);

                    List<User> users = new ArrayList<>();
                    users.add(rowMapper.mapRow(rs, 0));
                    users.add(rowMapper.mapRow(rs, 1));

                    return users;
                });

        List<User> userList = insertGroup.getUsers("sql", "1", "2");

        // Assert First Row
        assertFirstUser(userList.get(0));

        // Assert Second Row
        assertSecondUser(userList.get(1));
    }

    public void assertFirstUser(User user) {
        Assert.assertEquals(Integer.valueOf(412), user.getId());
        Assert.assertEquals("刘亦菲", user.getName());
        Assert.assertTrue(user.getFlag());
    }

    public void assertSecondUser(User user) {
        Assert.assertEquals(Integer.valueOf(300), user.getId());
        Assert.assertEquals("刘诗诗", user.getName());
        Assert.assertFalse(user.getFlag());
    }
}
2、ResultSetExtractor Mockito 测试

(1)创建 User 实体

java 复制代码
import lombok.Data;

@Data
public class User {

    private Integer id;

    private String name;

    private String applicant;

    private String address;

    private Boolean flag;
}

(2)JdbcTemplate 业务代码

java 复制代码
 public List<User> getUsers2(String sql, String name, String address) {

        return jdbcTemplate.query(sql, new ResultSetExtractor<List<User>>() {
            @Override
            public List<User> extractData(ResultSet rs) throws SQLException, DataAccessException {
                List<User> userList = new ArrayList<>();
                while (rs.next()) {
                    User user = new User();
                    user.setId(rs.getInt("ID"));
                    user.setName(rs.getString("Name"));
                    user.setApplicant(rs.getString("Applicant"));
                    user.setAddress(rs.getString("Address"));
                    user.setFlag(rs.getBoolean("Flag"));
                    userList.add(user);
                }
                return userList;
            }
        }, name, address);
    }

(3)Junit 测试

java 复制代码
 @Test
    public void test2() {
        Mockito.when(jdbcTemplate.query(
                        ArgumentMatchers.anyString(), ArgumentMatchers.any(ResultSetExtractor.class), ArgumentMatchers.any()))
                .thenAnswer((invocation) -> {
                    ResultSetExtractor<List<User>> resultSetExtractor =
                            (ResultSetExtractor<List<User>>) invocation.getArgument(1);

                    ResultSet rs = Mockito.mock(ResultSet.class);

                    // two times it returns true and third time returns false.
                    Mockito.when(rs.next()).thenReturn(true, true, false);

                    // Mock ResultSet to return two rows.
                    Mockito.when(rs.getInt(ArgumentMatchers.eq("ID")))
                            .thenReturn(412, 300);
                    Mockito.when(rs.getString(ArgumentMatchers.eq("Name")))
                            .thenReturn("刘亦菲", "刘诗诗");
                    Mockito.when(rs.getBoolean(ArgumentMatchers.eq("Flag")))
                            .thenReturn(true, false);

                    return resultSetExtractor.extractData(rs);
                });

        List<User> users = insertGroup.getUsers2("sql", "1", "2");

        Assert.assertEquals(Integer.valueOf(412), users.get(0).getId());
        Assert.assertEquals("刘亦菲", users.get(0).getName());
        Assert.assertTrue(users.get(0).getFlag());
    }
相关推荐
火烧屁屁啦16 分钟前
【JavaEE进阶】图书管理系统 - 贰
java·spring
xzzd_jokelin16 分钟前
Spring AI 接入 DeepSeek:开启智能应用的新篇章
java·人工智能·spring·ai·大模型·rag·deepseek
Gy-1-__31 分钟前
【springcloud】快速搭建一套分布式服务springcloudalibaba(一)
后端·spring·spring cloud
南山十一少5 小时前
Spring Security+JWT+Redis实现项目级前后端分离认证授权
java·spring·bootstrap
Tirzano7 小时前
springsecurity自定义认证
spring boot·spring
逸狼11 小时前
【JavaEE进阶】Spring MVC(3)
spring·java-ee·mvc
程序员侠客行12 小时前
Spring事务原理 二
java·后端·spring
小天努力学java13 小时前
AI赋能传统系统:Spring AI Alibaba如何用大模型重构机票预订系统?
人工智能·spring
五月茶13 小时前
Spring MVC
java·spring·mvc
2501_9032386514 小时前
Spring MVC配置与自定义的深度解析
java·spring·mvc·个人开发