Встроенный PostgreSql

Есть ли встроенный PostgreSql, чтобы мы могли модульно протестировать наше приложение, управляемое PostgreSql?

Поскольку PostgreSql имеет несколько диалектов, лучше использовать встроенный PostgreSql, чем другие встроенные базы данных.

6 ответов

Решение

Нет, нет встроенного PostgreSQL в смысле загружаемой в процессе базы данных как библиотеки. PostgreSQL ориентирован на процессы; каждый бэкэнд имеет один поток, и он порождает несколько процессов для выполнения работы. Это не имеет смысла как библиотека.

База данных H2 поддерживает ограниченное подмножество SQL-диалекта PostgreSQL и использование драйвера PgJDBC.

Что вы можете сделать, это initdb новая временная база данных, начните с pg_ctl на случайном порту, чтобы он не конфликтовал с другими экземплярами, запустите ваши тесты, а затем используйте pg_ctl чтобы остановить его и, наконец, удалить временную базу данных.

Я настоятельно рекомендую вам запускать временные postgres на портах не по умолчанию, чтобы вы не рисковали столкнуться с любым локально установленным PostgreSQL на машине, на которой выполняются тесты.

(Существует встроенный PostgreSQL в смысле ecpg, по сути, клиент PostgreSQL, встроенный в исходный код C в качестве расширений языка C на основе препроцессора. Для него по-прежнему требуется работающий сервер, и его использование является немного неприятным, не очень рекомендуется. упростить перенос из других баз данных.)

Это "встроенный" сервер PostgresSQL, разработанный для модульного тестирования с Java:

https://github.com/yandex-qatools/postgresql-embedded

Встроенный postgresql обеспечит независимый от платформы способ запуска двоичного файла postgres в модульных тестах. Большая часть кода была создана из процесса встраивания Flapdoodle OSS

Кроме того, существуют также аналогичные проекты для Mongo, Redis, Memcached и nodejs.

Я попробовал проект, предложенный @btiernay (yandex-qatools). Я провел несколько дней с этим, и без каких-либо оскорблений это слишком сложное решение, которое не работает в моем случае, так как я хотел загружать двоичные файлы из внутреннего репозитория, а не выходить в публичный Интернет. Теоретически это поддерживает, но на самом деле это не так.

OpenTable Embedded PostgreSQL Компонент

В итоге я использовал otj-pg-embedded, и он работает как шарм. Это было упомянуто в комментариях, поэтому я подумал упомянуть об этом и здесь.

Я использовал его как автономную БД, а не как правило для модульных тестов и локальной разработки.

Зависимость:

<dependency>
    <groupId>com.opentable.components</groupId>
    <artifactId>otj-pg-embedded</artifactId>
    <version>0.7.1</version>
</dependency>

Код:

@Bean
public DataSource dataSource(PgBinaryResolver pgBinaryResolver) throws IOException {
    EmbeddedPostgres pg = EmbeddedPostgres.builder()
        .setPgBinaryResolver(pgBinaryResolver)
        .start();


    // It doesn't not matter which databse it will be after all. We just use the default.
    return pg.getPostgresDatabase();
}

@Bean
public PgBinaryResolver nexusPgBinaryResolver() {
    return (system, machineHardware) -> {
        String url = getArtifactUrl(postgrePackage, system + SEPARATOR + machineHardware);
        log.info("Will download embedded Postgre package from: {}", url);

        return new URL(url).openConnection().getInputStream();
    };
}

private static String getArtifactUrl(PostgrePackage postgrePackage, String classifier) {
    // Your internal repo URL logic
}

Я использую в тестах экземпляр контейнера PostgreSQL. https://www.testcontainers.org/#about https://www.testcontainers.org/modules/databases/jdbc/

зависимости:

              <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter-api</artifactId>
            <version>5.7.2</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter-params</artifactId>
            <version>5.7.2</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter-engine</artifactId>
            <version>5.7.2</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.testcontainers</groupId>
            <artifactId>testcontainers</artifactId>
            <version>1.15.3</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.testcontainers</groupId>
            <artifactId>junit-jupiter</artifactId>
            <version>1.15.3</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.testcontainers</groupId>
            <artifactId>postgresql</artifactId>
            <version>1.15.3</version>
            <scope>test</scope>
        </dependency>

И сделаем тесты:

      @SpringBootTest
@ActiveProfiles({"test"})
@Testcontainers
class ApplicationTest {
    @Container
    static PostgreSQLContainer<?> postgreSQL = new PostgreSQLContainer<>("postgres:12.7");

    @DynamicPropertySource
    static void postgreSQLProperties(DynamicPropertyRegistry registry) {
        registry.add("spring.datasource.username", postgreSQL::getUsername);
        registry.add("spring.datasource.password", postgreSQL::getPassword);
    }


    @Test
    void someTests() {

    }

в application-test.yml:

      source:
  datasource:
    url: jdbc:tc:postgresql:12.7:///databasename

Вы можете использовать экземпляр контейнера PostgreSQL.

Поскольку вращение контейнера занимает считанные секунды, этого должно быть достаточно для юнит-тестов. Более того, в случае, если вам нужно сохранить данные, например, для расследования, вам не нужно сохранять весь контейнер, только файлы данных, которые могут быть отображены вне контейнера.

Один из примеров того, как это сделать, можно найти здесь.

Если вы хотите запустить внутрипроцессную версию postgres из набора тестов Integration (или аналогичного), встроенный в postgresql у меня отлично работает.

Я написал небольшой плагин maven, который можно использовать как оболочку maven для разветвленной версии postgresql-embedded.

Другие вопросы по тегам