Подтвердить что ты не робот

Запуск PostgreSQL только в памяти

Я хочу запустить небольшую базу данных PostgreSQL, которая работает только в памяти, для каждого unit test я пишу. Например:

@Before
void setUp() {
    String port = runPostgresOnRandomPort();
    connectTo("postgres://localhost:"+port+"/in_memory_db");
    // ...
}

В идеале у меня будет один исполняемый файл postgres, проверенный в элементе управления версиями, который будет использовать unit test.

Что-то вроде HSQL, но для postgres. Как я могу это сделать?

Можно ли получить такую ​​версию Postgres? Как я могу дать указание не использовать диск?

4b9b3361

Ответ 1

Это невозможно в Postgres. Он не предлагает движок in-process/in-memory, такой как HSQLDB или MySQL.

Если вы хотите создать автономную среду, вы можете поместить двоичные файлы Postgres в SVN (но это больше, чем просто один исполняемый файл).

Вам нужно будет запустить initdb, чтобы настроить тестовую базу данных, прежде чем вы сможете что-либо сделать с этим. Это можно сделать из командного файла или с помощью Runtime.exec(). Но обратите внимание, что initdb - это не то, что быстро. Вы определенно не хотите запускать это для каждого теста. Тем не менее, вы можете уйти от этого до своего тестового набора.

Однако, хотя это может быть сделано, я рекомендую иметь специальную установку Postgres, где вы просто воссоздаете свою тестовую базу данных, прежде чем запускать тесты.

Вы можете повторно создать тестовую базу данных, используя базу данных шаблонов, которая делает ее довольно быстрой ( лот быстрее, чем запуск initdb для каждого тестового прогона)

Ответ 2

Или вы можете создать TABLESPACE в ramfs/tempfs и создать все свои объекты там. Недавно я указал на статью о том, как это сделать в Linux.

Предупреждение

Это может поставить под угрозу целостность всего вашего кластера баз данных.
Прочтите добавленное предупреждение в руководстве.
Таким образом, это только вариант для расходных данных.

Для unit-testing он должен работать нормально. Если вы используете другие базы данных на одном компьютере, обязательно используйте отдельный кластер баз данных (который имеет свой собственный порт), чтобы быть в безопасности.

Ответ 3

(перевод моего ответа из Использование PostgreSQL в памяти и его обобщение):

Вы не можете запустить Pg in-process, in-memory

Я не могу понять, как запустить базу данных Postgres в памяти для тестирования. Возможно ли это?

Нет, это невозможно. 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 для быстрого тестирования

H2 Диалог PostgreSQL не является истинным заменителем

Некоторые люди вместо этого используют базу данных H2 в диалоговом режиме PostgreSQL для запуска тестов. Я думаю, что это почти так же плохо, как люди Rails, использующие SQLite для тестирования и PostgreSQL для производственного развертывания.

H2 поддерживает некоторые расширения PostgreSQL и эмулирует диалект PostgreSQL. Однако, это просто - эмуляция. Вы найдете области, где H2 принимает запрос, но PostgreSQL этого не делает, где поведение отличается и т.д.. Вы также найдете множество мест, где PostgreSQL поддерживает выполнение чего-то, что H2 просто не может - как функции окна, на момент написания.

Если вы понимаете ограничения этого подхода и доступ к базе данных прост, H2 может быть в порядке. Но в этом случае вы, вероятно, лучший кандидат на ORM, который абстрагирует базу данных, потому что вы все равно не используете ее интересные функции - и в этом случае вам больше не нужно заботиться о совместимости с базами данных.

Табличные пространства не являются ответом!

Не используйте табличное пространство для создания базы данных "in-memory". Мало того, что это не нужно, так как это никак не повлияет на производительность, но это также отличный способ нарушить доступ к любому другому, что вам может понадобиться в той же установке PostgreSQL. Документация 9.4 теперь содержит следующее предупреждение:

ПРЕДУПРЕЖДЕНИЕ

Несмотря на то, что он расположен за пределами основного каталога данных PostgreSQL, табличные пространства являются неотъемлемой частью кластера базы данных и не могут быть рассматривается как автономный набор файлов данных. Они зависят по метаданным, содержащимся в главном каталоге данных, и, следовательно, не может быть прикреплены к другому кластеру базы данных или подкреплены индивидуально. Аналогично, если вы потеряете табличное пространство (удаление файла, сбой диска, и т.д.), кластер базы данных может стать нечитаемым или не может запускаться. Размещение табличного пространства во временной файловой системе, такой как риск ramdisk надежность всего кластера.

потому что я заметил, что слишком много людей делают это и сталкиваются с трудностями.

(Если вы это сделали, вы можете mkdir отсутствующий каталог табличного пространства, чтобы начать работу PostgreSQL, а затем DROP отсутствующие базы данных, таблицы и т.д. Лучше просто не делать этого.)

Ответ 4

Теперь можно запустить экземпляр PostgreSQL в памяти в тестах JUnit через компонент Embedded PostgreSQL из OpenTable: https://github.com/opentable/otj-pg-embedded.

Добавив зависимость к библиотеке otj-pg-embedded (https://mvnrepository.com/artifact/com.opentable.components/otj-pg-embedded), вы можете запустить и остановить свой собственный экземпляр PostgreSQL в ваши @Before и @Afer hooks:

EmbeddedPostgres pg = EmbeddedPostgres.start();

Они даже предлагают правило JUnit для автоматического запуска JUnit и остановки сервера баз данных PostgreSQL для вас:

@Rule
public SingleInstancePostgresRule pg = EmbeddedPostgresRules.singleInstance();

Ответ 5

Вы можете использовать TestContainers, чтобы развернуть контейнер докеры PosgreSQL для тестов: http://testcontainers.viewdocs.io/testcontainers-java/usage/database_containers/

TestContainers предоставляют JUnit @Rule/@ClassRule: этот режим запускает базу данных внутри контейнера перед вашими испытаниями и затем сбрасывает его.

Пример:

public class SimplePostgreSQLTest {

    @Rule
    public PostgreSQLContainer postgres = new PostgreSQLContainer();

    @Test
    public void testSimple() throws SQLException {
        HikariConfig hikariConfig = new HikariConfig();
        hikariConfig.setJdbcUrl(postgres.getJdbcUrl());
        hikariConfig.setUsername(postgres.getUsername());
        hikariConfig.setPassword(postgres.getPassword());

        HikariDataSource ds = new HikariDataSource(hikariConfig);
        Statement statement = ds.getConnection().createStatement();
        statement.execute("SELECT 1");
        ResultSet resultSet = statement.getResultSet();

        resultSet.next();
        int resultSetInt = resultSet.getInt(1);
        assertEquals("A basic SELECT query succeeds", 1, resultSetInt);
    }
}

Ответ 6

В настоящее время существует версия PostgreSQL в памяти от российской поисковой компании Yandex: https://github.com/yandex-qatools/postgresql-embedded

Он основан на процессе встраивания Flapdoodle OSS.

Пример использования (со страницы github):

// starting Postgres
final EmbeddedPostgres postgres = new EmbeddedPostgres(V9_6);
// predefined data directory
// final EmbeddedPostgres postgres = new EmbeddedPostgres(V9_6, "/path/to/predefined/data/directory");
final String url = postgres.start("localhost", 5432, "dbName", "userName", "password");

// connecting to a running Postgres and feeding up the database
final Connection conn = DriverManager.getConnection(url);
conn.createStatement().execute("CREATE TABLE films (code char(5));");

Я использую это некоторое время. Это работает хорошо.

ОБНОВЛЕНО: этот проект больше не поддерживается активно

Please be adviced that the main maintainer of this project has successfuly 
migrated to the use of Test Containers project. This is the best possible 
alternative nowadays.

Ответ 7

Вы также можете использовать настройки конфигурации PostgreSQL (например, подробные в вопросе и принятом ответе здесь) для достижения производительности без необходимости использования базы данных в памяти.