Spring JdbcTemplate Junit 测试覆盖率 – 以 ResultSetExtractor / RowMapper 为例
1、RowMapper Mockito 测试
(1)创建实体类 User
@Data
public class User {
private Integer id;
private String name;
private String applicant;
private String address;
private Boolean flag;
}
(2)JdbcTemplate 业务代码
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 ListUser> getUsers(String sql, String name, String address) {
return jdbcTemplate.query(sql, new RowMapperUser>() {
@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 测试
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) -> {
RowMapperUser> rowMapper = (RowMapperUser>) 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);
ListUser> users = new ArrayList>();
users.add(rowMapper.mapRow(rs, 0));
users.add(rowMapper.mapRow(rs, 1));
return users;
});
ListUser> 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 实体
import lombok.Data;
@Data
public class User {
private Integer id;
private String name;
private String applicant;
private String address;
private Boolean flag;
}
(2)JdbcTemplate 业务代码
public ListUser> getUsers2(String sql, String name, String address) {
return jdbcTemplate.query(sql, new ResultSetExtractorListUser>>() {
@Override
public ListUser> extractData(ResultSet rs) throws SQLException, DataAccessException {
ListUser> 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 测试
@Test
public void test2() {
Mockito.when(jdbcTemplate.query(
ArgumentMatchers.anyString(), ArgumentMatchers.any(ResultSetExtractor.class), ArgumentMatchers.any()))
.thenAnswer((invocation) -> {
ResultSetExtractorListUser>> resultSetExtractor =
(ResultSetExtractorListUser>>) 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);
});
ListUser> 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());
}
服务器托管,北京服务器托管,服务器租用 http://www.fwqtg.net
CatFly【难度:1】 题目界面 下载附件,发现是dll文件,放到linux中运行一下,运行界面如图所示: 从上图中可以看到两处字符串,上面的字符串不断滚动,下方字符串在次数上不断累加,猜测上方字符串与flag相关。 静态调试 打开IDA,找到main函数 …