Единичное тестирование класса DAO, использующего Spring JDBC
У меня есть несколько объектов DAO, которые используются для извлечения информации из базы данных, и я действительно хочу написать некоторые автоматические тесты для них, но мне сложно понять, как это сделать.
Я использую Spring JdbcTemplate
для запуска реального запроса (через подготовленный оператор) и сопоставления результатов с объектом модели (через класс RowMapper
).
Если бы я должен был писать модульные тесты, я не уверен, как я должен/должен высмеивать объекты. Например, поскольку есть только чтения, я бы использовал фактическое соединение с базой данных, а не издевался над jdbcTemplate, но я не уверен, что это правильно.
Здесь (упрощенный) код для простейшего DAO пакета:
/**
* Implementation of the {@link BusinessSegmentDAO} interface using JDBC.
*/
public class GPLBusinessSegmentDAO implements BusinessSegmentDAO {
private JdbcTemplate jdbcTemplate;
private static class BusinessSegmentRowMapper implements RowMapper<BusinessSegment> {
public BusinessSegment mapRow(ResultSet rs, int arg1) throws SQLException {
try {
return new BusinessSegment(rs.getString(...));
} catch (SQLException e) {
return null;
}
}
}
private static class GetBusinessSegmentsPreparedStatementCreator
implements PreparedStatementCreator {
private String region, cc, ll;
private int regionId;
private GetBusinessSegmentsPreparedStatementCreator(String cc, String ll) {
this.cc = cc;
this.ll = ll;
}
public PreparedStatement createPreparedStatement(Connection connection)
throws SQLException {
String sql = "SELECT ...";
PreparedStatement ps = connection.prepareStatement(sql);
ps.setString(1, cc);
ps.setString(2, ll);
return ps;
}
}
public GPLBusinessSegmentDAO(DataSource dataSource) {
jdbcTemplate = new JdbcTemplate(dataSource);
}
public Collection<BusinessSegment> getBusinessSegments(String cc, String ll) {
return jdbcTemplate.query(
new GetBusinessSegmentsPreparedStatementCreator(cc, ll),
new BusinessSegmentRowMapper());
}
}
Любая идея будет оценена.
Спасибо!
Ответы
Ответ 1
Пожалуйста, посмотрите ниже ссылки:
Надеюсь, что это поможет.
EDIT:
Ниже приведена версия RowMapperTests для GitHub.
Ответ 2
Я рекомендую взломать вашу зависимость от класса JdbcTemplate
и вместо этого использовать интерфейс JdbcOperations
, например
public class GPLBusinessSegmentDAO implements BusinessSegmentDAO {
private final JdbcOperations jdbc;
public GPLBusinessSegmentDAO(DataSource dataSource) {
this(new JdbcTemplate(dataSource));
}
public GPLBusinessSegmentDAO(JdbcOperations jdbc) {
this.jdbc = jdbc;
}
// ... DAO methods here
}
Ваш unit test может вызывать второй конструктор, передавая объект mock JdbcOperations
. Поскольку все операции с БД выполняются с помощью объекта jdbc
, вы можете сделать это достаточно легко.
Ваш живой код может вызвать первый конструктор, как и раньше.
Ответ 3
Чтобы написать настоящий unit test для этого, вы не будете касаться реальной базы данных.
Однако вы можете найти более практичный переход в реальном DataSource к вашему базовому db, а тест метода getBusinessSegments() возвращает 0, 1 и многие результаты в зависимости от значений cc и ll, которые вы передаете.
Другим вариантом, заслуживающим изучения, является передача в DataSource встроенного Java DB, который был инициализирован вашей схемой в setUp/@Before метод. Я предполагаю, что вы действительно хотите проверить, что запрос SELECT... правильно отображает схему, поэтому такой тест будет ловить любые ошибки, возникающие во время выполнения, когда, например, изменяется схема.