50

是否有嵌入式 PostgreSql 以便我们可以对 PostgreSql 驱动的应用程序进行单元测试?

由于 PostgreSql 有一些方言,所以最好使用嵌入式 PostgreSql 本身,而不是使用其他嵌入式数据库。

嵌入并不一定意味着它必须嵌入到 JVM 进程中。它也不一定需要使用内存中的持久性。它应该由依赖管理(Maven、Gradle)自动加载,以便单元测试可以在每台机器上运行,而无需安装和配置本地 PostgreSQL 服务器。

4

6 回答 6

54

这是一个“嵌入式”PostgresSQL 服务器,专为 Java 单元测试而设计:

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

嵌入式 postgresql 将为在单元测试中运行 postgres 二进制文件提供一种平台中立的方式。大部分代码都是从Flapdoodle OSS 的嵌入过程中制作的

顺便说一句, MongoRedisMemcachednodejs也存在类似的项目。

于 2015-04-12T17:19:25.483 回答
36

不,从进程内可加载数据库即库的意义上说,没有嵌入式 PostgreSQL。PostgreSQL 是面向进程的;每个后端都有一个线程,它会产生多个进程来完成工作。作为图书馆没有意义。

H2 数据库支持PostgreSQL SQL 方言的有限子集和 PgJDBC 驱动程序的使用。

可以做的是initdb一个新的临时数据库pg_ctl在一个随机端口上启动它,这样它就不会与其他实例冲突,运行你的测试,然后pg_ctl用来停止它,最后删除临时数据库。

强烈建议您在非默认端口上运行临时 postgres ,这样您就不会冒险与运行测试的机器上任何本地安装的 PostgreSQL 发生冲突。

(在ecpg的意义上“嵌入式 PostgreSQL ,本质上是一个嵌入在 C源代码中的 PostgreSQL客户端,作为基于预处理器的 C 语言扩展。它仍然需要一个正在运行的服务器,而且使用起来有点讨厌,不推荐。它主要存在于使从各种其他数据库的移植更容易。)

于 2013-01-14T06:27:16.750 回答
30

我尝试了@btiernay (yandex-qatools) 建议的项目。我花了好几天的时间,没有任何冒犯,这是过度设计的解决方案,在我的情况下不起作用,因为我想从内部存储库下载二进制文件而不是去公共互联网。理论上它支持它,但实际上它不支持。

OpenTable 嵌入式 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
}
于 2016-12-13T10:52:25.500 回答
4

您可以使用 PostgreSQL 的容器实例。

由于旋转容器只需几秒钟,这对于单元测试应该已经足够了。此外,如果您需要保存数据,例如为了调查,您不需要保存整个容器,只需保存可以映射到容器外部的数据文件。

可以在此处找到如何执行此操作的示例之一。

于 2017-04-21T20:52:17.147 回答
3

如果您希望从集成(或类似)测试套件运行 postgres 的进程内版本,那么postgresql-embedded对我来说工作得很好。

我写了一个小的 maven 插件,它可以用作一个 maven 包装器,围绕一个 postgresql-embedded 的分叉版本。

于 2016-12-12T17:58:45.893 回答
1

我在测试中使用 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
于 2021-07-12T12:56:12.423 回答