嵌入式PostgreSQL for Java JUnit测试

blu*_*123 39 postgresql junit embedded-database database-driven maven

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

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

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

bti*_*nay 49

这是一个"嵌入式"PostgresSQL服务器,专为从Java进行单元测试而设计:

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

嵌入式postgresql将提供一种在平台测试中运行postgres二进制文件的平台中立方式.大部分代码都是从Flapdoodle OSS的嵌入过程中精心设计

另外,Mongo,Redis,Memcachednodejs也存在类似的项目.

  • 我团队的一些成员实施了https://github.com/opentable/otj-pg-embedded,似乎很好地为他们服务.使用Spring配置时,它具有更清晰的界面. (5认同)

Cra*_*ger 35

不,没有嵌入式PostgreSQL,就像进程内可加载的数据库作为库而言.PostgreSQL是面向流程的; 每个后端都有一个线程,它产生多个进程来完成工作.它作为一个图书馆并没有意义.

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

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

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

(这里在意义上的"嵌入式PostgreSQL的ECPG,基本上是一个PostgreSQL的客户端嵌入C 源代码基于预处理C语言扩展,它仍然需要一个正在运行的服务器,这是一个有点坏坏地使用,不推荐使用.它主要存在于从其他各种数据库中轻松移植.)

  • 你说"将一个面向流程的部分打包成一个库是没有意义的".为什么不?您现在可以使用Java库自动化IE.当然,流程将在幕后产生,但您仍然可以轻松地与Java库交谈以实现它.PostgreSQL也应该如此.你可以通过嵌入PostgreSQL安装程序来接近这个目标,但是有很多样板来设置它. (4认同)
  • @MihaiDanila绝对,这就是我的建议.只需捆绑Pg二进制文件的.zip,然后根据需要使用`pg_ctl`启动Pg.您可以在`initdb`和`initdb`参数之后编辑配置,通过环境变量或args控制诸如`pg_ctl`之类的东西等. (2认同)

Jan*_*yka 20

我尝试了@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>
Run Code Online (Sandbox Code Playgroud)

码:

@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
}
Run Code Online (Sandbox Code Playgroud)

  • 请参阅 dzone.com 文章:[*使用嵌入式 PostgreSQL 数据库进行测试*](https://dzone.com/articles/using-embedded-postgresql-databases-for-unit-testi) (2认同)

fir*_*ter 5

I am using the container instance of PostgreSQL in the tests. https://www.testcontainers.org/#about https://www.testcontainers.org/modules/databases/jdbc/

dependencies:

        <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>
Run Code Online (Sandbox Code Playgroud)

And do the tests:

@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() {

    }
Run Code Online (Sandbox Code Playgroud)

in application-test.yml:

source:
  datasource:
    url: jdbc:tc:postgresql:12.7:///databasename
Run Code Online (Sandbox Code Playgroud)