1

我正在为 spring jdbc dao 编写单元测试。测试的方法是:

public long getALong() {
return simpleJdbcTemplate.queryForObject("sql query here", new RowMapper<Long>() {
  public Long mapRow(ResultSet resultSet, int i) throws SQLException {
    return resultSet.getLong("a_long");
  }
});

}

这是我在测试中的内容:

public void testGetALong() throws Exception {
    final Long result = 1000L;
    context.checking(new Expectations() {{
      oneOf(simpleJdbcTemplate).queryForObject("sql_query", new RowMapper<Long>() {
        public Long mapRow(ResultSet resultSet, int i) throws SQLException {
          return resultSet.getLong("a_long");
        }
      });
      will(returnValue(result));
    }});
    Long seq = dao.getALong();
    context.assertIsSatisfied();
    assertEquals(seq, result);
  }

自然,测试不起作用(否则,我不会在这里问这个问题)。问题是测试中的rowmapper与DAO中的rowmapper不同。所以没有达到预期。

我试图with绕过 sql 查询和with(any(RowMapper.class))rowmapper。它也不起作用,抱怨“并非所有参数都给出了明确的匹配器:要么所有参数都必须由匹配器指定,要么所有参数都必须由值指定,你不能混合匹配器和值”

4

3 回答 3

2

也为查询字符串提供匹配器,例如

  oneOf(simpleJdbcTemplate).queryForObject(
      with( equal("sql_query") ),
      with( any(RowMapper.class) )
  );
于 2012-04-12T17:03:42.720 回答
2

我想你可能在这里遗漏了几点。您的第一次尝试在模拟中重现了目标代码的行为。你真正想测试什么?

对于这种测试,我更喜欢编写一个针对真实数据库的集中测试。多年前我尝试模拟出 JDBC 并后悔了。在这种代码中通常失败的是与数据库的关系,而不是 java 代码本身。

这实际上是一个查询(它不会改变对象外部世界的状态),所以我倾向于使用allowing()子句而不是oneOf(). 这是相同的底层机制,但更好地表达了意图。

最后,与其context.assertIsSatisfied()直接调用,不如考虑使用

@RunWith(JMock.class)

在测试的顶部。

于 2012-04-13T09:53:04.380 回答
1

我通过在最后添加解决了这个问题with(any(Object.class))

oneOf(jdbcTemplate).queryForObject(with(equal("sql_query")), with(any(RowMapper.class)), with(any(Object.class)));

我认为 jmock 无法找到正确的调用方法,因为 queryForObject 方法过载太多了。

于 2012-04-12T17:53:59.640 回答