В статье о выполнении запросов с помощью Spring JDBC я нарушил одно из правил написания модульных тестов: тест метода создающего нового заказчика ничего не проверял:
@Test public void testAdd() { testedObject.add("new@example.org"); }
А не проверял этот тест ничего потому, что не было возможности сделать запрос к базе, который бы вернул свежесозданную запись. В CustomerRepository нет метода, который возвращает запись по её e-mail, а какой у новой записи id мы не знаем.
Но id можно узнать ???? Метод update() позволяет передать ему callback интерфейс KeyHolder, в котором, после выполнения запроса, будет храниться сгенерированный id строки.
private static class CreationStatement implements PreparedStatementCreator { private String email; public CreationStatement(final String e) { this.email = e; } @Override public final PreparedStatement createPreparedStatement(final Connection con) throws SQLException { PreparedStatement ps = con.prepareStatement(CREATE_QUERY); ps.setString(1, email); return ps; } } @Override public Number add(String email) { KeyHolder key = new GeneratedKeyHolder(); jdbcTemplate.update(new CreationStatement(email), key); return key.getKey(); }
К сожалению, из-за различающихся реализаций JDBC драйверов баз данных для использования update() и KeyHolder приходится спускаться на более низкий уровень и вручную создавать PreparedStatement используя интерфейс PreparedStatementCreator. Это приводит к некоторой многословности кода.
Тест к этой реализации может теперь проверить, действительно ли в базе данных появляется созданный объект:
@Test public void testAdd() { Number id = testedObject.add("new@example.org"); assertThat(testedObject.getEmail((Long) id), is("new@example.org")); }