{"id":22059225,"url":"https://github.com/opentable/otj-pg-embedded","last_synced_at":"2025-05-14T11:08:51.055Z","repository":{"id":20441151,"uuid":"23718011","full_name":"opentable/otj-pg-embedded","owner":"opentable","description":"Java embedded PostgreSQL component for testing","archived":false,"fork":false,"pushed_at":"2025-04-24T20:02:33.000Z","size":510,"stargazers_count":695,"open_issues_count":2,"forks_count":184,"subscribers_count":43,"default_branch":"master","last_synced_at":"2025-04-24T20:24:38.670Z","etag":null,"topics":["database","docker","java","platform-java","postgres","testcontainers","unit-testing"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/opentable.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2014-09-05T20:53:30.000Z","updated_at":"2025-04-16T07:13:05.000Z","dependencies_parsed_at":"2022-07-31T19:48:15.960Z","dependency_job_id":"bf3d6c91-63b2-4a9f-a462-5bb73f86169f","html_url":"https://github.com/opentable/otj-pg-embedded","commit_stats":null,"previous_names":[],"tags_count":43,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/opentable%2Fotj-pg-embedded","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/opentable%2Fotj-pg-embedded/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/opentable%2Fotj-pg-embedded/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/opentable%2Fotj-pg-embedded/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/opentable","download_url":"https://codeload.github.com/opentable/otj-pg-embedded/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254129482,"owners_count":22019628,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["database","docker","java","platform-java","postgres","testcontainers","unit-testing"],"created_at":"2024-11-30T17:27:38.956Z","updated_at":"2025-05-14T11:08:51.031Z","avatar_url":"https://github.com/opentable.png","language":"Java","funding_links":[],"categories":["测试"],"sub_categories":[],"readme":"OpenTable Embedded PostgreSQL Component\n=======================================\n\nNote: This library requires Java 11+. However, Flyway 10 **requires Java 17**. The last pure Java 11 release was 1.0.3\n\nAllows embedding PostgreSQL into Java application code, using Docker containers.\nExcellent for allowing you to unit\ntest with a \"real\" Postgres without requiring end users to install  and set up a database cluster.\n\n## Recent Changes (and the reasons behind them)\n\nThe release of 1.0 brings major changes to the innards of this library.\nPrevious pre 1.x versions used an embedded tarball. This was extremely fast (a major plus), but we switched to a docker based version\nfor these reasons:\n\n* **Advantages:** \n  * multi architecture support. This has become a huge issue for us with the introduction of the Mac M1 (and Windows ARM, Linux ARM)/\n  * The same container works the same way on every OS - Mac, Windows, Linux. And we can use the official postgresql docker image by default.\n  * You need a tarball for every linux distribution as PG 10+ no longer ship a \"universal binary\" for linux. This means a lot of support and maintenance work, and we frankly didn't have time for it.\n  * Easy to switch docker image tag to upgrade versions - no need for a whole new pg-embedded version.\n  * More maintainable and secure (you can pull docker images you trust, instead of trusting our tarballs running in your security context)\n  * Trivial to do a build oneself based on the official Postgres image adding extensions, setup scripts etc. - see https://github.com/docker-library/docs/blob/master/postgres/README.md for details.\n* **Admittedly, a few disadvantages**\n  * Slower than running a tarball (2-5x slower). This can add up a lot with many tests. You can work around this by changing the lifecycle, but then you have tests that are possibly non reproducible if they modify the same tables.\n  * A few API compatibility changes and options have probably disappeared. Feel free to submit PRs.\n  * Docker in Docker can be dodgy to get running. (See below for some tips)\n \nSee also `Alternatives Considered` - there are other alternative approaches that you may find useful.\n\n## Before filing tickets.\n\n1. Before filing tickets, please test your docker environment etc. If using podman or lima instead of \"true docker\", state so, and realize that the\ndocker socket api provided by these apps is not 100% compatible, as we've found to our sadness. We'll be revisiting\ntesting these in the future. We've managed to get PodMan working, albeit not 100% reliably.\n2. **No further PRs or tickets will be accepted for the pre 1.0.0 release, unless community support arises for the `legacy` branch.** Please\nbase any PRs for pre 1.x against the `legacy` branch.\n3. We primarily use Macs and Ubuntu Linux at OpenTable. We'll be happy to try to help out otherwise, but other platforms, such\nas Windows depend primarily on community support. We simply don't have the time or hardware. Happy to merge PRs though\n\nSee \"Alternatives Considered\" as well if this library doesn't appear to fit your needs.\n\n## Basic Usage\n\nIn your JUnit test just add (for JUnit 5 example see **Using JUnit5** below):\n\n```\n@Rule\npublic SingleInstancePostgresRule pg = EmbeddedPostgresRules.singleInstance();\n```\n\nThis simply has JUnit manage an instance of EmbeddedPostgres (start, stop). You can then use this to get a DataSource with: `pg.getEmbeddedPostgres().getPostgresDatabase();`  \n\nAdditionally, you may use the [`EmbeddedPostgres`](src/main/java/com/opentable/db/postgres/embedded/EmbeddedPostgres.java) class directly by manually starting and stopping the instance; see [`EmbeddedPostgresTest`](src/test/java/com/opentable/db/postgres/embedded/EmbeddedPostgresTest.java) for an example.\n\nDefault username/password is: postgres/postgres and the default database is 'postgres'\n\n**The port exposed on the host is random and ephemeral so always use the getDatasource, getUrl methods**\n\n## Sample of Embedded Postgres direct Usage\n\n```\npublic void testDatabaseName() throws IOException,SQLException{\n        EmbeddedPostgres db=EmbeddedPostgres.builder().start();\n        Datasource dataSource = db.getPostgresDatabase();\n        .... use the datasource then ...\n        db.close();\n        }\n```\n\nThe builder includes options to set the image, the tag, the database name, and various configuration options.\n\n## Migrators (Flyway or Liquibase)\n\nYou can easily integrate Flyway or Liquibase database schema migration:\n##### Flyway\n```\n@Rule \npublic PreparedDbRule db =\n    EmbeddedPostgresRules.preparedDatabase(\n        FlywayPreparer.forClasspathLocation(\"db/my-db-schema\"));\n        \n        \nPlease note: Recent versions of FLyway will probably hang if you have concurrent indexing. Use\nthe features described in the 1.0.3 changelog to disable the broken lock feature. See the FlywarePreparerTest\n```\n\n##### Liquibase\n```\n@Rule\npublic PreparedDbRule db = \n    EmbeddedPostgresRules.preparedDatabase(\n            LiquibasePreparer.forClasspathLocation(\"liqui/master.xml\"));\n```\n\nThis will create an independent database for every test with the given schema loaded from the classpath.\nDatabase templates are used so the time cost is relatively small, given the superior isolation truly\nindependent databases gives you.\n\n## Postgres version\n\nThe default is to use the docker hub registry and pull a tag, hardcoded in `EmbeddedPostgres`. Currently, this is \"13-latest\",\nas this fits the needs of OpenTable, however you can change this easily. This is super useful, both to use a newer version\nof Postgres, or to build your own DockerFile with additional extensions.\n\nYou may change this either by environmental variables or by explicit builder usage\n\n### Environmental Variables\n\n1. If `PG_FULL_IMAGE` is set, then this will be used and is assumed to include the full docker image name. So for example this might be set to `docker.otenv.com/postgres:mytag`\n2. Otherwise, if `TESTCONTAINERS_HUB_IMAGE_NAME_PREFIX` is set, this is prefixed to \"postgres\" (adding a slash if it doesn't exist). So for example this might be set to \"docker.otenv.com/\"\n3. Otherwise, the default is used as defined above.\n\n### Explicit builder\n\nIt is possible to change postgres image and tag in the builder:\n\n```\n    EmbeddedPostgres.builder()\n        .setTag(\"10\")\n        .start();\n```\n\nor use custom image:\n\n```\n    EmbeddedPostgres.builder()\n        .setImage(DockerImageName.parse(\"docker.otenv.com/super-postgres\"))\n        .start();\n```\n\nThere are also options to set the initDB configuration parameters, or other functional params, the bind mounts, and\nthe network.\n\n## Using JUnit5\n\nJUnit5 does not have `@Rule`. So below is an example for how to create tests using JUnit5 and embedded postgres, it creates a Spring context and uses JDBI:\n\n```java\n@ExtendWith(SpringExtension.class)\n@SpringBootTest(classes = DaoTestUsingJunit5.MockDBConfiguration.class)\nclass DaoTestUsingJunit5 {\n    interface MyDao {}\n\n    @Inject\n    MyDao myDao;\n\n    @Test\n    void someTest() {\n        // ....\n    }\n\n    @Import(DaoTestUsingJunit5.GlobalMockDBConfiguration.class)\n    @Configuration\n    static class MockDBConfiguration {\n        @Bean\n        public MyDao dao(Jdbi jdbi) {\n            return jdbi.onDemand(MyDao.class);\n        }\n    }\n\n    /**\n     * This class is here as inner class for brevity,\n     * but it's better to have only one for all tests.\n     */\n    @Configuration\n    public static class GlobalMockDBConfiguration {\n        @Bean(\"jdbiUser\")\n        @Primary\n        Jdbi jdbi() throws SQLException {\n            DatabasePreparer db = FlywayPreparer.forClasspathLocation(\"db/migration\");\n\n            Jdbi jdbi = Jdbi.create(PreparedDbProvider.forPreparer(db).createDataSource())\n                    .installPlugin(new PostgresPlugin())\n                    .installPlugin(new SqlObjectPlugin())\n                    .setTransactionHandler(new SerializableTransactionRunner());\n\n            return configureJdbi(jdbi);\n        }\n\n        static Jdbi configureJdbi(Jdbi jdbi) {\n            // possible actions:\n            // - register immutables\n            // - set up mappers, etc\n            return jdbi;\n        }\n    }\n}\n```\n\n\n\n\n## Yes, Junit4 is a compile time dependency\n\nThis is because TestContainers has a long outstanding bug to remove this -https://github.com/testcontainers/testcontainers-java/issues/970\nIf you exclude Junit4, you get nasty NoClassDefFound errors.\n\nIf you only use Junit5 in your classpath, and bringing in Junit4 bothers you (it does us, sigh), then\nyou can do the following:\n\n* add maven exclusions to the testcontainers modules you declare dependencies on to strip out junit:junit. This by itself\nwould still lead to NoClassDefFound errors.\n* add a dependency on io.quarkus:quarkus-junit4-mock , which imports empty interfaces of the required classes. This is\na hack and a cheat, but what can you do?\n\nWe initially excluded junit4 ourselves, which led to confusing breakages for junit5 users...\n\n## Some new options and some lost from Pre 1.0\n\n* You can't wire to a local postgres, since that concept doesn't make sense here. So that's gone.\n* You can add bind mounts and a Network (between two containers), since those are docker concepts, and can\nbe very useful.\n* By the way, TestContainers does support ~/.docker/config.json for setting authenticated access to Docker, but we've not tested it.\n\n## Docker in Docker, authentication notes\n\nWe've been able to get this working in our CICD pipeline with the following\n\n```\nTESTCONTAINERS_HOST_OVERRIDE=localhost\nTESTCONTAINERS_HUB_IMAGE_NAME_PREFIX=dockerhub.otenv.com/\n```\n\nThe first parameter corrects for testcontainers getting confused whether to address the hosting container or the \"container inside the container\".\nThe second parameter (which outside OpenTable would point to your private Docker Registry) avoids much of the Docker Rate Limiting issues. \n\nSee https://github.com/testcontainers/testcontainers-java/issues/4596 for more information\n\n## Alternatives considered\n\nWe updated this library primarily for convenience of current users to allow them to make a reasonably smooth transition to a Docker based\ntest approach.\n\n* Why not just use Testcontainers directly?\n\nYou can, and it should work well for you. The builders, the api compatibility, the wrapping around Flyway - that's the added value.\nBut certainly there's no real reason you can't use [TestContainers](https://testcontainers.com/) directly - they have their own Junit4 and Junit5 Rules/Extensions.\n\n* Why not use a maven plugin approach like `fabric8-docker-maven`?\n\nHonestly I suspect this is a better approach in that it doesn't try to maintain its own version of the Docker API, and\nruns outside the tests, reducing issues like forking and threading conflicts. However, it would have been too major an overhaul\nfor our users.\n\n* \"I really prefer the old embedded postgres approach. It's faster.\"\n\n   We recommend those who prefer the embedded tarball use [Embedded Postgres](https://github.com/zonkyio/embedded-postgres) which was forked back into 2018 from the embedded branch of this library and is kept reasonably up to date.\n   \n   Another alternative is Flapdoodle's embedded postgres, but that is deprecated in favor of testcontainers too.\n\n   Both libraries suffer from many of the cons that bedeviled upkeep of this library for years, but they are certainly viable options\n   for many.\n\n----\nCopyright (C) 2017-2024 OpenTable, Inc\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fopentable%2Fotj-pg-embedded","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fopentable%2Fotj-pg-embedded","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fopentable%2Fotj-pg-embedded/lists"}