如何通过模拟覆盖junit测试中的RowMapper块?

时间:2019-05-29 07:51:49

标签: java spring-boot jdbc junit

我尝试模拟一个查询,因为我使用rowmapper块作为输出。我为new RowMapper<Object>() {}创建了一个块,在块内,我在映射中设置值并返回该映射。代码已成功运行,但是在代码覆盖范围内,我无法覆盖RowMapper块内的代码。

我尝试使用thenAnswer覆盖该阻止,但出现异常

jdbcTempCPA.query(sql, new Object[] { orderNo, orderNo }, new RowMapper<Object>() {
                @Override
                public Object mapRow(ResultSet rs, int rowNum) throws SQLException {
                    ret.put("GetValue",
                            CommonUtil.correctNullString(rs.getString("SELECTED")));
                    ret.put("Indicator"
                            CommonUtil.correctNullString(rs.getString("ADVISORY_INDICATOR")));
                    return ret;
                }
            });

这是覆盖上面代码的junit代码

Mockito.when(jdbcTemplateMock.query(Mockito.anyString(), Mockito.any(Object[].class),Matchers.<RowMapper<Map<String, String>>>any())).thenReturn(ret);

1 个答案:

答案 0 :(得分:0)

如果要对传递给模拟的参数做进一步的断言,则应使用captors

如果您使用的是MockitoJUnitRunner,则可以这样创建捕获器:

@Captor
private ArgumentCaptor<RowMapper<Object>> anyRowMapper;

此外,您还必须提供一个ResultSet,最简单的方法也可能是对其进行模拟:

@Mock
private ResultSet resultSet;

在测试中,您现在可以编写:

// Set up mocks
when(resultSet.getString("SELECTED")).thenReturn("someString");
when(resultSet.getString("ADVISORY_INDICATOR")).thenReturn("someOtherString");
when(jdbcTemplate.query(anyString(), any(), any()).thenReturn(ret);

// Actually invoke your logic
service.doSomething();

// Capture arguments passed to jdbcTemplate.query(..)
verify(jdbcTemplate).query(anyString(), any(), anyRowMapper.capture());

现在您已经捕获了RowMapper,就可以实际调用它了。考虑到此RowMapper本身返回了ret,您可以像这样为它编写进一步的断言:

Map<String, String> ret = anyRowMapper.getValue().mapRow(resultSet, 123);
assertThat(ret).contains(
    entry("GetValue", "someString"),
    entry("Indicator", "someOtherString")
);

这是最美丽的测试吗?考虑到模拟的数量,可能不会。在这种情况下,您可能需要编写一个集成测试,然后对带有测试数据的虚拟数据库运行代码。