использование JMock для написания модульного теста для простого весеннего JDBC DAO

Я пишу модульный тест для 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 в тесте отличается от rowmapper в DAO. Так что ожидание не оправдалось.

Я попытался поставить with вокруг запроса sql и with(any(RowMapper.class)) для rowmapper. Это тоже не сработает, жалуется на то, что "не всем параметрам были заданы явные сопоставители: либо все параметры должны быть указаны сопоставителями, либо все должны быть указаны значениями, нельзя смешивать сопоставители и значения"


person Quincy    schedule 12.04.2012    source источник
comment
Взгляните на использование теста RowMapper из Github самой Poutsma: github.com/SpringSource/spring-framework/blob/3.1.x/   -  person    schedule 12.04.2012


Ответы (3)


Также укажите сопоставитель для строки запроса, например.

  oneOf(simpleJdbcTemplate).queryForObject(
      with( equal("sql_query") ),
      with( any(RowMapper.class) )
  );
person Alexander Pogrebnyak    schedule 12.04.2012
comment
нет, тоже не работает. Я получаю, что не всем параметрам были заданы явные сопоставители: либо все параметры должны быть указаны сопоставителями, либо все должны быть указаны значениями, вы не можете смешивать сопоставители и ошибки значений. - person Quincy; 12.04.2012
comment
@ Куинси, ) отсутствовал после sql_query. - person Alexander Pogrebnyak; 12.04.2012

Я думаю, что вы можете пропустить пару моментов здесь. Ваша первая попытка воспроизвела поведение целевого кода в макете. Что вы действительно пытаетесь проверить?

Для такого рода тестов я предпочитаю писать сфокусированные тесты, которые затрагивают реальную базу данных. Я пытался издеваться над JDBC много лет назад и сожалел об этом. Что обычно не работает в таком коде, так это связь с базой данных, а не с самим кодом Java.

На самом деле это запрос (он не меняет состояние мира вне объекта), поэтому я предпочитаю использовать предложение allowing(), а не oneOf(). Это тот же основной механизм, но он лучше выражает намерение.

Наконец, вместо прямого вызова context.assertIsSatisfied() рассмотрите возможность использования

@RunWith(JMock.class)

в верхней части теста.

person Steve Freeman    schedule 13.04.2012

Я решил проблему, добавив with(any(Object.class)) в конце.

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

Я думаю, что у jmock возникли проблемы с поиском правильного метода для вызова, поскольку метод queryForObject сильно перегружен.

person Quincy    schedule 12.04.2012
comment
Было бы неплохо, если бы вы сказали нам, что метод, который вы тестируете, принимает 3 аргумента вместо 2. - person Alexander Pogrebnyak; 13.04.2012