增加 JdbcTemplate 模拟的代码覆盖率
increasing code coverage for JdbcTemplate mocking
我正在为单元测试用例嘲笑 JdbcTemplate,因为不想影响实际的数据库集成。
但它正在降低我的代码覆盖率(红色表示缺少覆盖率)。
下面是使用的片段。使用用户定义的映射器也会发生同样的情况。
final List<String> resultList = new ArrayList<String>();
resultList.add("test1");
resultList.add("test2");
final JdbcTemplate template = Mockito.mock(JdbcTemplate.class);
Mockito.when(
template.query(Mockito.anyString(), Mockito.any(Object[].class),
Mockito.any(RowMapper.class))).thenReturn(resultList);
sampleDao.setJdbcTemplate(template);
关于 increasing code
dao class 覆盖的任何想法。在我的案例中,所有方法都不适合用户定义的行映射器。
您正在模拟 jdbcTemplate,因此您的生产 jdbcTemplate 没有机会被执行并触发 rowMapper。如果你真的想模拟它,那么你必须以某种方式模拟查询,它仍然会触发 rowMapper 并传递给它假的 ResultSet。您还可以提取 rowMapper 并单独测试它。但它会让你花更多的时间写测试,而在 return 中一无所获。不要这样做。数据库代码应在与实际数据库的集成测试期间进行测试。
一种方法如下:
final List<String> resultList = new ArrayList<String>();
resultList.add("test1");
resultList.add("test2");
final JdbcTemplate template = mock(JdbcTemplate.class);
when(template.query(anyString(), any(Object[].class), any(RowMapper.class)))
.thenAnswer(new Answer<List<String>>() {
@Override
public Object answer(InvocationOnMock invocation) throws Throwable {
// Fetch the method arguments
Object[] args = invocation.getArguments();
// Fetch the row mapper instance from the arguments
RowMapper<String> rm = (RowMapper<String>) args[2];
// Create a mock result set and setup an expectation on it
ResultSet rs = mock(ResultSet.class);
String expected = "value returned by query";
when(rs.getString(1)).thenReturn(expected);
// Invoke the row mapper
String actual = rm.mapRow(rs, 0);
// Assert the result of the row mapper execution
assertEquals(expected, actual);
// Return your created list for the template#query call
return resultList;
}
});
但是如您所见,测试行映射器的代码很多:)
就个人而言,我更愿意进行集成测试,或者将行映射器移动到它自己的 class 并单独对其进行单元测试。
我正在为单元测试用例嘲笑 JdbcTemplate,因为不想影响实际的数据库集成。
但它正在降低我的代码覆盖率(红色表示缺少覆盖率)。
下面是使用的片段。使用用户定义的映射器也会发生同样的情况。
final List<String> resultList = new ArrayList<String>();
resultList.add("test1");
resultList.add("test2");
final JdbcTemplate template = Mockito.mock(JdbcTemplate.class);
Mockito.when(
template.query(Mockito.anyString(), Mockito.any(Object[].class),
Mockito.any(RowMapper.class))).thenReturn(resultList);
sampleDao.setJdbcTemplate(template);
关于 increasing code
dao class 覆盖的任何想法。在我的案例中,所有方法都不适合用户定义的行映射器。
您正在模拟 jdbcTemplate,因此您的生产 jdbcTemplate 没有机会被执行并触发 rowMapper。如果你真的想模拟它,那么你必须以某种方式模拟查询,它仍然会触发 rowMapper 并传递给它假的 ResultSet。您还可以提取 rowMapper 并单独测试它。但它会让你花更多的时间写测试,而在 return 中一无所获。不要这样做。数据库代码应在与实际数据库的集成测试期间进行测试。
一种方法如下:
final List<String> resultList = new ArrayList<String>();
resultList.add("test1");
resultList.add("test2");
final JdbcTemplate template = mock(JdbcTemplate.class);
when(template.query(anyString(), any(Object[].class), any(RowMapper.class)))
.thenAnswer(new Answer<List<String>>() {
@Override
public Object answer(InvocationOnMock invocation) throws Throwable {
// Fetch the method arguments
Object[] args = invocation.getArguments();
// Fetch the row mapper instance from the arguments
RowMapper<String> rm = (RowMapper<String>) args[2];
// Create a mock result set and setup an expectation on it
ResultSet rs = mock(ResultSet.class);
String expected = "value returned by query";
when(rs.getString(1)).thenReturn(expected);
// Invoke the row mapper
String actual = rm.mapRow(rs, 0);
// Assert the result of the row mapper execution
assertEquals(expected, actual);
// Return your created list for the template#query call
return resultList;
}
});
但是如您所见,测试行映射器的代码很多:)
就个人而言,我更愿意进行集成测试,或者将行映射器移动到它自己的 class 并单独对其进行单元测试。