Проблема

Наверняка многие из вас (тут я обращаюсь к Java разработчикам) разок да применяли Mockito в своих unit тестах. Зачастую жизненные реалии enterprise разработки далеки от той идеальной картинки, которая мелькает в академических материалах, книгах, статьях типа “tutorial” и на конференциях по разработке. Представим, что мы написали компонент, использующий множество сущностей. Пусть это будет batch загрузка данных в БД. Десятки DAO, Entity, валидаций … Каждая новая нить проверок бизнес-логики вынуждает нас создать еще один тест. Но что делать с данными? В режиме отладки мы, возможно, задумывались: а почему нам нельзя достать код для генерации данных по объектам Entity, которые мы сформировали из БД? В интернете порой всплывают подобные вопросы, например тут.

Mockito

Одним из способов решить эту проблему - “замокать” DAO, загружающие данные из таблиц. И здесь начинается хаос. Однако описать вручную создание нескольких объектов не представляет большой сложности.

User user = new User();
user.setName("fake user");
user.setAge("24");

UserDAO u = Mockito.mock(UserDAO.class);
Mockito.when(u.findByName(anyString()).thenReturn(user);

Здесь мы создаем своего фейкового пользователя, которого мы впоследствии вернем из замоканного DAO репозитория там, где мы его используем. Но что, если тест потребует одновременное взаимодействие нескольких таблиц, где затраты на создание соответствующих entity займет больше времени, чем на разработку?

Embedded Database

В моей практике порой вырисовывается грань по сложности написания unit теста, переступив которую я предпочту просто вытащить действительные данные из таблиц в виде SQL запросов (вместе со скриптами создания таблиц). А потом подключить H2 встроенную библиотеку, которая заполнится данными и будет работать не используя файловую систему и другие “пахнущие интеграцией” ресурсами. Более того, H2 имеет поддержку диалектов различных реляционных баз данных, что позволяет нам избежать адаптации SQL скриптов под другую СУБД.

jdbc:h2:mem:test;DB_CLOSE_DELAY=-1

Строка подключения для H2 в оперативной памяти выглядит таким образом. Код работы unit теста будет абсолютно простым: наши данные будут переданы непосредственно через jdbc. Единственное, что нам потребуется сделать - поменять DataSource на H2.

    @Bean
    @Profile("test")
    public DataSource dataSource() {
        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setDriverClassName("org.h2.Driver");
        dataSource.setUrl("jdbc:h2:mem:db;DB_CLOSE_DELAY=-1");
        dataSource.setUsername("sa");
        dataSource.setPassword("sa");
 
        return dataSource;
    }

Вопрос висящий в воздухе - а как мы будем создавать SQL скрипт? Вручную? Зощим? Ответ: в современных SQL обозревателях зачастую есть готовые функции для генерации тех или иных записей в БД. Даже в Intellij IDEA есть такая.

IDEA SQL dump

Исходя из этого можно сделать следующий вывод: если создание entity вручную требует много времени, можно воспользоваться embedded database, отведя роль создания данных SQL запросам. А вы как думаете, камрады? Жду ответов в комментариях :)