Модульное тестирование класса 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());
    }

}

Любая идея будет оценена.

Спасибо!


person Alex Ciminian    schedule 23.03.2011    source источник
comment
Вы можете взглянуть на Acolyte, платформу для модульного тестирования сохраняемости JDBC с реальной изоляцией.   -  person cchantep    schedule 05.07.2017


Ответы (3)


Пожалуйста, ознакомьтесь с приведенными ниже ссылками:

  1. Тестирование запросов SQL с помощью Spring и DbUnit
  2. MockObjects или DBUnit для тестирования кода с использованием JdbcTemplate

Надеюсь, это поможет.

РЕДАКТИРОВАТЬ:

Вот GitHub-версия RowMapperTests для удобства.

person Nilesh    schedule 23.03.2011
comment
Теперь, когда SpringSource переместился на github, вы можете найти RowMapperTests здесь. РЕДАКТИРОВАТЬ: я обновил ответ новой ссылкой. - person Tony R; 23.12.2011

Я рекомендую сломать вашу зависимость от класса 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
}

Ваш модульный тест может вызывать второй конструктор, передавая фиктивный объект JdbcOperations. Поскольку все операции с БД выполняются через объект jdbc, вы можете достаточно легко смоделировать это.

Ваш рабочий код может вызывать первый конструктор, как и раньше.

person skaffman    schedule 23.03.2011

Чтобы написать для этого настоящий модульный тест, вам не придется касаться реальной базы данных. Однако вы можете счесть более практичным передать реальный источник данных в базовую базу данных и проверить, что метод getBusinessSegments() возвращает 0, 1 и многие результаты в зависимости от значений cc и ll, которые вы передаете.

Еще один вариант, который стоит изучить, — передать источник данных встроенной Java DB, который был инициализирован вашей схемой в методе setUp/@Before. Я предполагаю, что вы действительно хотите проверить, что запрос SELECT... правильно отображается в схему, поэтому такой тест будет обнаруживать любые ошибки, возникающие во время выполнения, когда схема, скажем, изменяется.

person npellow    schedule 23.03.2011