Автор оригинала: Vlad Mihalcea.
Когда я начал писать Высокопроизводительное сохранение Java , я понял, что мне нужен репозиторий GitHub для размещения всех тестовых примеров, которые мне нужны для фрагментов кода в моей книге, и именно так родился высокопроизводительный репозиторий GitHub с сохранением java .
Репозиторий GitHub с высокой производительностью и сохраняемостью java представляет собой набор интеграционных тестов и утилит, позволяющих с максимальной легкостью тестировать функции JDBC, JPA, Hibernate и jOOQ.
Коллекция интеграционных тестов и утилит, позволяющих тестировать функции JDBC, JPA, Hibernate и jOOQ – @vlad_mihalcea https://t.co/FOCcW98MAs https://t.co/FOCcW98MAs
Поскольку этот репозиторий действительно важен для работы над моим блогом, книгой или видеокурсами , я решил записать следующее видео и поделиться им с вами на YouTube:
Это видео-лишь один из многих потрясающих видеоуроков, которые вы можете найти в моем высокопроизводительном видеокурсе сохранения Java .
При работе с системой баз данных, когда вы хотите протестировать код уровня доступа к данным, модульные тесты не очень помогают вам. Вместо этого вам нужны интеграционные тесты, которые выполняются в системе баз данных, аналогичной той, которая у вас есть в производстве.
Именно так мы тестируем проект Hibernate ORM That’s also how we are testing the Hibernate ORM project
Теперь в репозитории GitHub с высокой производительностью и сохраняемостью java вы найдете множество интеграционных тестов. На момент написания этой статьи существует более 440 интеграционных тестов, охватывающих наиболее распространенные сценарии, с которыми вы можете столкнуться при использовании JDBC, JPA или Hibernate.
В то время как для производственной системы вы действительно хотите использовать Flyway для управления схемой базы данных, когда ваша цель состоит в создании автономных интеграционных тестов, инструмент Hibernate hbm2ddl – отличный выбор.
Таким образом, вам не нужно писать какие-либо сценарии DDL для вашей базы данных для интеграционных тестов, и это дает вам большое преимущество при переключении с одной реляционной базы данных на другую.
До тех пор, пока вы продолжаете As long as you extend AbstractTest
, all you need to do is to override the entities
base class method: Абстрактный тест
@Override protected Class>[] entities() { return new Class>[] { Post.class, PostDetails.class, }; }
И сущности могут быть инкапсулированы в интеграционные тесты, чтобы каждый тест работал по своей собственной уникальной модели без влияния изменений, происходящих за пределами исходного кода рассматриваемого интеграционного теста:
@Entity(name = "Post") @Table(name = "post") public static class Post { @Id @GeneratedValue private Long id; private String title; //Getters and setters omitted for brevity } @Entity(name = "PostDetails") @Table(name = "post_details") public static class PostDetails { @Id private Long id; @Column(name = "created_on") private Date createdOn; @Column(name = "created_by") private String createdBy; @OneToOne @MapsId private Post post; //Getters and setters omitted for brevity }
Удивительность этого метода проявляется, когда вы начинаете переопределять метод базы данных
базового класса.
Если вы заявляете, что хотите использовать MySQL:
@Override protected Database database() { return Database.MYSQL; }
В вашем тесте будет использоваться следующая схема базы данных MySQL:
create table post ( id bigint not null, title varchar(255), primary key (id) ) engine=InnoDB create table post_details ( created_by varchar(255), created_on datetime(6), post_id bigint not null, primary key (post_id) ) alter table post_details add constraint FKmcgdm1k7iriyxsq4kukebj4ei foreign key (post_id) references post (id)
Если вы хотите, чтобы этот тест выполнялся на PostgreSQL, просто измените метод database
следующим образом:
@Override protected Database database() { return Database.POSTGRESQL; }
И Hibernate hbm2ddl сделает свое дело:
create sequence hibernate_sequence start 1 increment 1 create table post ( id int8 not null, title varchar(255), primary key (id) ) create table post_details ( created_by varchar(255), created_on timestamp, post_id int8 not null, primary key (post_id) ) alter table if exists post_details add constraint FKmcgdm1k7iriyxsq4kukebj4ei foreign key (post_id) references post
Круто, правда?
Просто потому, что вам нужно протестировать код JDBC, это не значит, что ваш код должен быть подробным. Благодаря методу do В JDBC
, который вы автоматически наследуете от Абстрактный тест
, ваша логика интеграционного теста выглядит следующим образом:
doInJDBC(connection -> { try (Statement statement = connection.createStatement()) { statement.addBatch( "insert into post (title, version, id) " + "values ('Post no. 1', 0, 1)" ); statement.addBatch( "insert into post_comment (post_id, review, version, id) " + "values (1, 'Post comment 1.1', 0, 1)" ); statement.addBatch( "insert into post_comment (post_id, review, version, id) " + "values (1, 'Post comment 1.2', 0, 2)" ); int[] updateCounts = statement.executeBatch(); assertEquals(3, updateCounts.length); } });
За кулисами метод doInJDBC
выполняет все необходимые действия для запуска этого кода:
- получено соединение с базой данных,
- транзакция запускается автоматически,
- выполняется лямбда-код Java 8,
- в случае успеха транзакция будет совершена,
- в случае сбоя транзакция откатывается,
- соединение закрывается независимо от того, что происходит выше.
В том же духе именно так вы выполняете логику доступа к данным JPA и гибернации:
Post _post = doInJPA(entityManager -> { Post post = new Post("First post"); entityManager.persist(post); return post; }); doInJPA(entityManager -> { Post post = entityManager.getReference( Post.class, _post.getId() ); PostDetails details = new PostDetails("John Doe"); details.setPost(post); entityManager.persist(details); }); doInJPA(entityManager -> { PostDetails details = entityManager.find( PostDetails.class, _post.getId() ); assertNotNull(details); entityManager.flush(); details.setPost(null); });
Метод doInJPA
заботится о:
- создание JPA
EntityManager
, - запуск JPA
EntityTransaction
, - выполняется лямбда-код Java 8,
- при успешном выполнении
EntityTransaction
выполняется, - в случае сбоя/| entityтранзакция
откатывается,
- EntityManager
закрывается независимо от того, что происходит выше.
Если вы хотите протестировать код доступа к данным, просто разветвите мой высокопроизводительный репозиторий GitHub с сохранением java и сосредоточьтесь на логике тестирования, вместо загрузки JDBC, JPA или гибернации или управления схемой базы данных или базовыми ресурсами, задействованными во время выполнения тестов.