Spring Data JPA & Hibernate with Cucumber

Для автоматизации тестирования работа с БД идет часто вместе. Напишем небольшую реализацию работы с БД при помощи Spring Data JPA & Hibernate. Наглядно будет понятно, на сколько Spring помогает уменьшить код при работе в данном случае с БД. Также обернем все шаги проверок в тестовый фреймворк Cucumber на примере нескольких тестов, что бы было понятно, как код можно применить в написании авто тестов. Добавим несколько проверок на Junit 5. Ранером для тестов будем использовать Cucumber.

Использовал:

Spring Data JPA Hibernate MsSql Database Cucumber Junit 5

Необходимо выполнить:
– Создать БД и тестовые таблицы;
– Сконфигурировать подключение к БД MySql;
– Реализовать контроллер для запросов в БД (Spring Data JPA);
– Написать несколько тестов на Cucumber;

Создаём таблицу Person

CREATE TABLE Person (
id INT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,
first_name VARCHAR(150),
last_name VARCHAR(150),
birthday DATE,
email VARCHAR(150),
phone VARCHAR(150),
job VARCHAR(150)
);

Добавляем в таблицу тестовые записи.

INSERT INTO Person (first_name, last_name, birthday, email, phone, job)
VALUES
('Eva', 'Muflikhunova', NULL, 'eva@gotoqa.ru', '+7-916-548-7777', 'newborn'),
('Gleb', 'Muflikhunov', NULL, 'gleb@gotoqa.ru', '+7-916-548-8888', 'newborn'),
('Vika', 'Muflikhunova', DATE '2015-12-17', 'vika@gotoqa.ru', '+7-916-548-9999', 'Sber'),
('John', 'Travolta', DATE '1980-12-17', 'john@gotoqa.ru', '+7-916-548-1111', 'BBC'),
('Ken', 'Barby', DATE '1930-12-17', 'ken@gotoqa.ru', '+7-916-548-0000', 'Alatoys');

Создаём таблицу Geography без поля с ключевым идентификатором, в данной таблице ключом будет являться связка двух полей country и city.

CREATE TABLE Geography
(
    country    VARCHAR(150),
    city       VARCHAR(150),
    population INT,
    LANGUAGE   VARCHAR(150)
);

Также наполняем таблицу тестовыми данными

INSERT INTO Geography (country, city, population, LANGUAGE)
VALUES
('Russia', 'Moscow', 14674859, 'russian'),
('Italy', 'Roma', 60317116, 'italian'),
('Tanzania', 'Dodoma', 48261942, 'swahili'),
('Usa', 'Washington D.C.', 328239523, 'English');

Следующим шагом создадим maven проект и подключим необходимые зависимости в pom.xml

Подключаем библотеки фрейворка Spring

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-orm</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.data</groupId>
            <artifactId>spring-data-jpa</artifactId>
            <version>2.1.5.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>${spring.version}</version>
        </dependency>

Библиотека Hibernate в качестве реализации JPA будет использоваться

        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-core</artifactId>
            <version>${hibernate.version}</version>
        </dependency>

MySql драйвер для соединения с БД

       <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.14</version>
            <scope>runtime</scope>
        </dependency>

Добавлем Lombok для более чистого кода, с реализацией к примеру гетеров – сетеров через аннотации.

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.16.18</version>
        </dependency>

Для запуска тестов будем использовать фрейворки Cucumber и Junit 5

        <dependency>
            <groupId>info.cukes</groupId>
            <artifactId>cucumber-java</artifactId>
            <version>${cucumber.version}</version>
        </dependency>
        <dependency>
            <groupId>info.cukes</groupId>
            <artifactId>cucumber-junit</artifactId>
            <version>${cucumber.version}</version>
        </dependency>
        <dependency>
            <groupId>info.cukes</groupId>
            <artifactId>cucumber-spring</artifactId>
            <version>${cucumber.version}</version>
        </dependency>
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter-api</artifactId>
            <version>${junit.jupiter.version}</version>
        </dependency>
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter-engine</artifactId>
            <version>${junit.jupiter.version}</version>
        </dependency>

Проект настроен, можем переходить к написанию кода.

Теперь необходимо сгенерировать сущности Entity для мапинга каждой таблицы. Аннотацию @Entity используется для сопоставления класса PersonEntity с таблицей Person. Поле id помечено @Id и @GeneratedValue, оно является первичным ключом и его значение генерируется автоматически.

Для таблицы Person

@Entity
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Table(name = "Person", schema = "actors")
public class PersonEntity {
 
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Integer id;
 
    @Column(name = "first_name")
    private String firstName;
 
    @Column(name = "last_name")
    private String lastName;
    private Date birthday;
    private String email;
    private String phone;
    private String job;
 
}

Для таблицы Geography описание сущности Entity будет дополнено статичным классом primary key (PK), это значение и будет составлять уникальный ключ Id, который требуется для корректной работы Hibernate.

@Entity
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Table(name = "Geography", schema = "actors")
public class GeographyEntity {
 
    @EmbeddedId
    private PK pk;
 
    @Basic
    private Integer population;
 
    @Basic
    private String language;
 
    @Embeddable
    @Data
    public static class PK implements Serializable {
 
        @Basic
        @Column(name = "country", insertable = false, updatable = false)
        private String country;
 
        @Basic
        @Column(name = "city", insertable = false, updatable = false)
        private String city;
    }
}

Структура проекта такая:

ru.gotoqa.config – Каталог содержит классы конфигурации Spring, параметры подключения к БД и тд
ru.gotoqa.entity – Каталог для сущностей мапинга к таблицам
ru.gotoqa.repository – Содержит интерфейсы которые расширяет интерфейс CrudRepository из Spring Data JPA
ru.gotoqa.service – Сервис классы для управления транзакциями, отделяет бизнесс уровень от реализации DAO в репозитории
ru.gotoqa.steps – Определяет реализацию шагов фремворка Cucumber
src/test/java/resources/*.feature – Каталог для написания тестовых сценариев (feature) фремворка Cucumber

Как в учебнике, тесты не видят сервисы и реализацию работы с БД, каждый слой отвечает исключительно за свою работу.

После запуска тестов, получаем отчёт в консоли.

Feature: Сheck records in a db table
 
  Scenario: Check records in Person table (should be 5)
    Then get all: 5 records from Person table
 
  Scenario: Check records in Geography table (should be 4)
    Then get all: 4 records from Geography table
2 Scenarios (2 passed)
2 Steps (2 passed)
0m0,243s

Ссылка на полную версию проекта на GitHub:
Github SpringDataJPA

Releated Post