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());
}