138

作成する単体テストごとに、メモリ内でのみ実行される小さなPostgreSQLデータベースを実行したいと思います。例えば:

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

理想的には、単体テストで使用するバージョン管理に1つのpostgres実行可能ファイルをチェックインします。

のようなものHSQLですが、postgres用です。どうやってやるの?

そのようなPostgresバージョンを入手できましたか?ディスクを使用しないように指示するにはどうすればよいですか?

4

10 に答える 10

99

(インメモリPostgreSQLの使用とそれを一般化することから私の答えを移動します):

Pgをインプロセス、インメモリで実行することはできません

テストのためにインメモリPostgresデータベースを実行する方法がわかりません。出来ますか?

いいえ、できません。PostgreSQLはCで実装され、プラットフォームコードにコンパイルされます。H2やDerbyとは異なり、をロードしjarて使い捨てのインメモリDBとして起動することはできません。

これもCで記述され、プラットフォームコードにコンパイルされるSQLiteとは異なり、PostgreSQLはインプロセスでロードすることもできません。マルチスレッドアーキテクチャではなくマルチプロセッシングであるため、複数のプロセス(接続ごとに1つ)が必要です。マルチプロセッシング要件は、ポストマスターをスタンドアロンプ​​ロセスとして起動する必要があることを意味します。

代わりに:接続を事前設定します

特定のホスト名/ユーザー名/パスワードが機能することを期待するテストを作成し、実行の最後にテストCREATE DATABASEに使い捨てデータベースを利用させることをお勧めします。DROP DATABASEプロパティファイルからデータベース接続の詳細を取得し、ターゲットプロパティ、環境変数などを構築します。

単体テストに提供するユーザーがスーパーユーザーではなくCREATEDB、権限を持つユーザーのみである限り、関心のあるデータベースが既に存在する既存のPostgreSQLインスタンスを使用しても安全です。最悪の場合、他のデータベースでパフォーマンスの問題が発生します。そのため、テストのために完全に分離されたPostgreSQLインストールを実行することを好みます。

代わりに:テスト用に使い捨てのPostgreSQLインスタンスを起動します

または、テストハーネスでバイナリを検索し、実行してデータベースを作成し、に変更して、実行してランダムポートで開始し、ユーザーを作成し、DBを作成して、テストを実行することもできます。テストを実行する前に、複数のアーキテクチャ用のPostgreSQLバイナリをjarにバンドルし、現在のアーキテクチャ用のPostgreSQLバイナリを一時ディレクトリに解凍することもできます。initdbpostgresinitdbpg_hba.conftrustpostgres

個人的には、それは避けるべき大きな痛みだと思います。テストDBを設定する方がはるかに簡単です。ただし、 ;でのinclude_dirサポートの登場により、少し簡単になりました。postgresql.confこれで、1行を追加して、残りのすべての構成ファイルを生成して書き込むことができます。

PostgreSQLによるより高速なテスト

テスト目的でPostgreSQLのパフォーマンスを安全に改善する方法の詳細については、このトピックについて以前に書いた詳細な回答を参照してください:高速テストのためにPostgreSQLを最適化する

H2のPostgreSQL方言は真の代替ではありません

代わりに、PostgreSQLダイアレクトモードでH2データベースを使用してテストを実行する人もいます。これは、テストにSQLiteを使用し、本番環境にPostgreSQLを使用しているRailsの人々とほぼ同じくらい悪いことだと思います。

H2はいくつかのPostgreSQL拡張機能をサポートし、PostgreSQL方言をエミュレートします。しかし、それはまさにそれです-エミュレーション。H2はクエリを受け入れますが、PostgreSQLは受け入れない領域、動作が異なる領域などがあります。また、執筆時点では、ウィンドウ関数のように、PostgreSQLがH2ではできないことをサポートしている場所もたくさんあります。

このアプローチの制限を理解していて、データベースアクセスが単純な場合は、H2で問題ない可能性があります。しかし、その場合は、データベースの興味深い機能を使用していないため、データベースを抽象化するORMの候補としておそらく適しています。その場合、データベースの互換性についてはそれほど気にする必要はありません。

表スペースは答えではありません!

表領域を使用して「メモリ内」データベースを作成しないでください。とにかくパフォーマンスを大幅に向上させないので不要であるだけでなく、同じPostgreSQLインストールで気になる他のアクセスを中断するための優れた方法でもあります。9.4のドキュメントには、次の警告が含まれています

警告

メインのPostgreSQLデータディレクトリの外にある場合でも、テーブルスペースはデータベースクラスタの不可欠な部分であり、データファイルの自律的なコレクションとして扱うことはできません。これらはメインデータディレクトリに含まれるメタデータに依存しているため、別のデータベースクラスタに接続したり、個別にバックアップしたりすることはできません。同様に、テーブルスペースを失うと(ファイルの削除、ディスク障害など)、データベースクラスターが読み取れなくなったり、起動できなくなったりする可能性があります。ramdiskなどの一時ファイルシステムにテーブルスペースを配置すると、クラスター全体の信頼性が低下します。

あまりにも多くの人がこれをやっていて問題にぶつかっているのに気づいたからです。

(これを行った場合はmkdir、欠落しているテーブルスペースディレクトリを使用してPostgreSQLを再起動し、DROP欠落しているデータベース、テーブルなどを実行できます。実行しない方がよいでしょう。)

于 2014-06-16T00:53:52.980 に答える
70

またはTABLESPACE、ramfs / tempfsにを作成し、そこにすべてのオブジェクトを作成することもできます。
私は最近、Linuxでまさにそれを行うことについての記事を指摘されました。元のリンクは無効です。しかし、それはアーカイブされました(Arsinclairによって提供されました):

警告

これにより、データベースクラスタ全体の整合性が危険にさらされる可能性があります。
マニュアルに追加された警告をお読みください。
したがって、これは消費可能なデータのオプションにすぎません。

ユニットテストの場合は、問題なく動作するはずです。同じマシンで他のデータベースを実行している場合は、安全のために別のデータベースクラスター(独自のポートを持つ)を使用してください。

于 2011-10-24T08:08:48.607 に答える
55

これはPostgresでは不可能です。HSQLDBやMySQLのようなインプロセス/インメモリエンジンは提供していません。

自己完結型の環境を作成したい場合は、PostgresバイナリをSVNに入れることができます(ただし、これは単一の実行可能ファイル以上のものです)。

これを使用して何かを行う前に、initdbを実行してテストデータベースをセットアップする必要があります。これは、バッチファイルから、またはRuntime.exec()を使用して実行できます。ただし、initdbは高速なものではないことに注意してください。テストごとにそれを実行したくないことは間違いありません。ただし、テストスイートの前にこれを実行することはできません。

ただし、これは可能ですが、テストを実行する前にテストデータベースを再作成するだけの専用のPostgresインストールを使用することをお勧めします。

テンプレートデータベースを使用してテストデータベースを再作成できます。これにより、テストデータベースの作成が非常に高速になります(テストの実行ごとにinitdbを実行するよりもはるかに高速です)

于 2011-10-24T08:20:13.953 に答える
38

これで、OpenTableのEmbedded PostgreSQLコンポーネントを介してJUnitテストでPostgreSQLのメモリ内インスタンスを実行できるようになりました:https ://github.com/opentable/otj-pg-embedded 。

otj-pg-embeddedライブラリ(https://mvnrepository.com/artifact/com.opentable.components/otj-pg-embedded)に依存関係を追加することで、@BeforeとでPostgreSQLの独自のインスタンスを開始および停止できます。 @Aferフック:

EmbeddedPostgres pg = EmbeddedPostgres.start();

また、JUnitがPostgreSQLデータベースサーバーを自動的に開始および停止するJUnitルールも提供しています。

@Rule
public SingleInstancePostgresRule pg = EmbeddedPostgresRules.singleInstance();
于 2017-09-21T11:18:08.513 に答える
18

TestContainersを使用して、テスト用のPosgreSQL Dockerコンテナーを起動できます: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);
    }
}
于 2017-09-09T09:09:52.337 に答える
9

現在、Yandexという名前のロシアの検索会社からのPostgreSQLのメモリ内バージョンがあります:https ://github.com/yandex-qatools/postgresql-embedded

これは、FlapdoodleOSSの埋め込みプロセスに基づいています。

使用例(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.
于 2018-12-24T10:47:20.480 に答える
7

NodeJSを使用している場合は、pg-mem(免責事項:私が作成者です)を使用して、postgresデータベースの最も一般的な機能をエミュレートできます。

PGの動作を複製する完全なメモリ内の分離されたプラットフォームに依存しないデータベースがあります(ブラウザでも実行されます)。

ここに、単体テストでの使用方法を示す記事を書きました。

于 2020-08-03T15:21:07.667 に答える
3

また、PostgreSQLの構成設定(ここで質問や受け入れられた回答で詳しく説明されているものなど)を使用して、必ずしもインメモリデータベースに頼ることなくパフォーマンスを実現することもできます。

于 2013-06-10T20:45:18.980 に答える
3

dockerを使用できる場合は、テスト用にpostgresqlデータディレクトリをメモリにマウントできます

docker run --tmpfs=/data -e PGDATA=/data postgres
于 2021-05-12T19:23:50.287 に答える
0

Javaを使用している場合、主に単体テストに使用されるメモリ内の「埋め込み」postgres環境を提供する、効果的に使用されていることを確認したライブラリがあります。

https://github.com/opentable/otj-pg-embedded

答えを探してこの検索結果にアクセスした場合、これでユースケースを解決できる可能性があります。

于 2021-12-16T19:02:49.913 に答える