Я хочу запустить небольшую базу данных PostgreSQL, которая работает только в памяти, для каждого написанного мной модульного теста. Например:
@Before
void setUp() {
String port = runPostgresOnRandomPort();
connectTo("postgres://localhost:"+port+"/in_memory_db");
// ...
}
В идеале у меня должен быть один исполняемый файл postgres, зарегистрированный в системе контроля версий, который будет использовать модульный тест.
Что-то вроде HSQL
, но для postgres. Как я могу это сделать?
Могу ли я получить такую версию Postgres? Как я могу запретить ему использовать диск?
testcontainers
, по сути, позволяющим вашему тесту запускать одноразовый, dockerized, postgres-instance. См. Github.com/testcontainers/testcontainers-java/blob/master/…(Перемещаю свой ответ из раздела Использование PostgreSQL в памяти и обобщаю его):
Вы не можете запустить Pg в процессе, в памяти
Нет, это невозможно. PostgreSQL реализован на C и скомпилирован в код платформы. В отличие от H2 или Derby, вы не можете просто загрузить
jar
и запустить его как одноразовую базу данных в памяти.В отличие от SQLite, который также написан на C и скомпилирован в код платформы, PostgreSQL также не может быть загружен в процессе. Для этого требуется несколько процессов (по одному на соединение), потому что это многопроцессорная, а не многопоточная архитектура. Требование многопроцессорности означает, что вы должны запускать postmaster как отдельный процесс.
Вместо этого: предварительно настройте соединение
Я предлагаю просто написать ваши тесты, ожидая, что определенное имя хоста / имя пользователя / пароль будет работать, и иметь тестовую привязку
CREATE DATABASE
к одноразовой базе данных, а затемDROP DATABASE
в конце запуска. Получите сведения о подключении к базе данных из файла свойств, целевых свойств сборки, переменной среды и т. Д.Безопасно использовать существующий экземпляр PostgreSQL, который у вас уже есть базы данных, о которых вы заботитесь, если пользователь, который вы указываете для своих модульных тестов, не является суперпользователем, а только пользователем с
CREATEDB
правами. В худшем случае вы создадите проблемы с производительностью в других базах данных. По этой причине я предпочитаю запускать полностью изолированную установку PostgreSQL для тестирования.Вместо этого: запустите одноразовый экземпляр PostgreSQL для тестирования
С другой стороны , если вы действительно острыми вы могли бы иметь свой тест Жгут определить местонахождение
initdb
иpostgres
бинарных файлов, запускать ,initdb
чтобы создать базу данных, изменить ,pg_hba.conf
чтобыtrust
, запустить ,postgres
чтобы запустить его на произвольный порт, создать пользователь, создать базу данных, и запустить тесты . Вы даже можете связать двоичные файлы PostgreSQL для нескольких архитектур в банке и распаковать файлы для текущей архитектуры во временный каталог перед запуском тестов.Лично я считаю, что этого следует избегать; проще настроить тестовую БД. Однако с появлением
include_dir
поддержки стало немного легчеpostgresql.conf
; теперь вы можете просто добавить одну строку, а затем написать сгенерированный файл конфигурации для всех остальных.Более быстрое тестирование с PostgreSQL
Для получения дополнительной информации о том, как безопасно повысить производительность PostgreSQL в целях тестирования, см. Подробный ответ, который я написал по этой теме ранее: Оптимизация PostgreSQL для быстрого тестирования
Диалект PostgreSQL H2 не является настоящей заменой
Некоторые люди вместо этого используют базу данных H2 в режиме диалекта PostgreSQL для запуска тестов. Я думаю, что это почти так же плохо, как и люди из Rails, использующие SQLite для тестирования и PostgreSQL для производственного развертывания.
H2 поддерживает некоторые расширения PostgreSQL и имитирует диалект PostgreSQL. Однако это всего лишь эмуляция. Вы найдете области, где H2 принимает запросы, а PostgreSQL - нет, где поведение отличается и т . Д. Вы также найдете множество мест, где PostgreSQL поддерживает выполнение того, что H2 просто не может - например, оконных функций на момент написания.
Если вы понимаете ограничения этого подхода и у вас простой доступ к базе данных, H2 может подойти. Но в этом случае вы, вероятно, лучший кандидат на ORM, который абстрагирует базу данных, потому что вы все равно не используете ее интересные функции - и в этом случае вам больше не нужно так сильно заботиться о совместимости базы данных.
Табличные пространства - это не ответ!
Вы не использовать табличный для создания базы данных «в памяти». Это не только не нужно, так как это не сильно повлияет на производительность, но и отличный способ нарушить доступ к любому другому, что может вас заинтересовать в той же установке PostgreSQL. Документация 9.4 теперь содержит следующее предупреждение :
потому что я заметил, что слишком много людей делали это и сталкивались с проблемами.
(Если вы это сделали, вы можете
mkdir
указать отсутствующий каталог табличного пространства, чтобы снова запустить PostgreSQL, а затемDROP
недостающие базы данных, таблицы и т. Д. Лучше просто не делать этого.)источник
initdb
установить там совершенно новый Pg. Но на самом деле нет особой разницы между Pg, настроенным для быстрого тестирования в обычном хранилище (fsync = off и другие функции обеспечения надежности / безопасности данных отключены), чем у RAM-диска, по крайней мере, в Linux.Или вы можете создать TABLESPACE в ramfs / tempfs и создать там все свои объекты.
Недавно мне указали на статью о том, как делать именно это в Linux .
Предупреждение
Это может поставить под угрозу целостность всего кластера базы данных .
Прочтите добавленное предупреждение в руководстве.
Так что это только вариант для расходных данных.
Для модульного тестирования он должен работать нормально. Если вы запускаете другие базы данных на том же компьютере, обязательно используйте отдельный кластер базы данных (у которого есть собственный порт) на всякий случай.
источник
initdb
новый экземпляр postgres в tempfs или ramdisk. Как не использовать табличный в tempfs и т.д., это хрупкое и бессмысленно. Вам лучше использовать обычное табличное пространство и создаватьUNLOGGED
таблицы - он будет работать аналогично. И это не повлияет на производительность WAL и факторы fsync, если вы не предпримете действий, которые поставят под угрозу целостность всей БД (см. Stackoverflow.com/q/9407442/398670 ). Не делай этого.Теперь можно запускать экземпляр PostgreSQL в памяти в ваших тестах JUnit через встроенный компонент PostgreSQL из OpenTable: https://github.com/opentable/otj-pg-embedded .
Добавляя зависимость к встроенной библиотеке otj-pg ( https://mvnrepository.com/artifact/com.opentable.components/otj-pg-embedded ), вы можете запускать и останавливать собственный экземпляр PostgreSQL в ваших @Before и @Afer крючки:
Они даже предлагают правило JUnit для автоматического запуска и остановки JUnit вашего сервера базы данных PostgreSQL:
источник
@Rule
с@ExtendWith
? Просто используйте.start()
in@BeforeAll
?DataSource embeddedPostgresDS = EmbeddedPostgres.builder().start().getPostgresDatabase();
Вы можете использовать TestContainers, чтобы развернуть контейнер докеров PosgreSQL для тестов: http://testcontainers.viewdocs.io/testcontainers-java/usage/database_containers/
TestContainers предоставляет JUnit @ Rule / @ ClassRule : этот режим запускает базу данных внутри контейнера перед вашими тестами и затем разрывает ее.
Пример:
источник
Теперь есть версия PostgreSQL в памяти от российской поисковой компании под названием Яндекс: https://github.com/yandex-qatools/postgresql-embedded.
Он основан на процессе встраивания Flapdoodle OSS.
Пример использования (со страницы github):
Я пользуюсь им некоторое время. Это работает хорошо.
ОБНОВЛЕНО : этот проект больше не поддерживается
источник
Вы также можете использовать параметры конфигурации PostgreSQL (например, подробно описанные в вопросе и принятый ответ здесь ) для достижения производительности, не обязательно прибегая к базе данных в памяти.
источник
Если вы используете NodeJS, вы можете использовать pg-mem (отказ от ответственности: я являюсь автором) для имитации наиболее распространенных функций базы данных postgres.
У вас будет полная в памяти, изолированная, независимая от платформы база данных, реплицирующая поведение PG (она даже работает в браузерах ).
Я написал статью , чтобы показать , как использовать его для ваших модульных тестов здесь .
источник