web-dev-qa-db-ja.com

H2 postgresqlモードが機能していないようです

こんにちは私のアプリケーションはPostgresデータベースにアクセスし、事前定義された多くのクエリ(ランク、パーティション、複雑な結合など)を持っています。ここで、小さなテストデータを使用して、これらのクエリの動作を単体テストします。だから私はH2/Junitから始めました。ランク、パーティション、更新時の複雑なケースなどのPostgresクエリのほとんどがわかったので、すべてのpostgresクエリがH2で機能すると考えて、H2 PosgreSQL互換モードを使用することを考えました。

PostgreSQLモードを使用するには、データベースのURL jdbc:h2:〜/ test; MODE = PostgreSQLまたはSQLステートメントのSET MODE PostgreSQLを使用して、H2のドキュメントを読みました。

SET MODE PostgreSQLを使用してモードを有効にし、rank()を含み、postgresで機能するクエリの1つを起動しようとしましたが、H2で機能しませんでした。それは私に次の例外を与えます

Function "RANK' not found; in SQL statement

私がH2とデータベースのテストに不慣れな方を案内してください。前もって感謝します。 H2 Posgress互換モードではpostgresクエリを起動できると考えて、H2 jdbcドライバーを使用してpostgresクエリを起動しています。

20
Umesh K

だから私はすべてのpostgresクエリがH2で動作すると思ってH2 PosgreSQL互換モードを使用することを考えました

それは真実ではないようです。

H2はPostgreSQL構文をエミュレートし、いくつかの機能と拡張機能をサポートしようとします。 PostgreSQLの動作と完全に一致することは決してなく、すべての機能をサポートしているわけではありません。

使用できるオプションは次のとおりです。

  • テストではPostgreSQLを使用します。または
  • H2でサポートされていない機能の使用を停止する

テストにはPgを使用することをお勧めします。 initdbがpostgresインスタンスであり、テストのために起動して、後で破棄するテストハーネスを書くのは比較的簡単です。

コメントに基づいて更新:

「単体」テストと「統合」テストの間に明確な境界はありません。この場合、H2も外部コンポーネントです。 Puristユニットテストでは、テストハーネスの一部として、クエリに対するダミーレスポンダーが用意されます。 H2に対するテストは、PostgreSQLに対するテストと同じくらい「統合」テストです。インプロセスおよびインメモリであることは便利ですが、機能的には重要ではありません。

単体テストを行う場合は、アプリの別のデータベースターゲットを記述して、「PostgreSQL」、「SybaseIQ」などのターゲットと一緒にする必要があります。 「MockDatabase」と言ってください。これは、クエリから期待される結果を返すだけです。実際にはクエリを実行せず、残りのコードの動作をテストするためだけに存在します。

個人的には、これは非常に時間の浪費だと思いますが、それはユニットテストの純粋主義者が外部依存関係をテストハーネスに導入しないようにするために行うことです。

(統合ではなく)DBコンポーネントの単体テストを主張するが、モックインターフェイスを作成できない/作成できない場合は、代わりに既存のインターフェイスを使用する方法を見つける必要があります。 H2はこれの妥当な候補です。ただし、H2で機能する新しいクエリのセットを使用して新しいバックエンドを作成する必要があります。PostgreSQLバックエンドを再利用することはできません。すでに確立しているように、H2はPostgreSQLで使用する必要があるすべての機能をサポートしているわけではないため、H2で同じことを行うためのさまざまな方法を見つける必要があります。 1つのオプションは、実際のアプリケーションのスキーマを完全に無視して、「期待される」結果とそれらの結果を返す単純なクエリを含む単純なH2データベースを作成することです。ここでの唯一の欠点は、維持するのが大変なことですが、それは単体テストです。

個人的には、PostgreSQLでテストします。ナローインターフェースで明確に定義されたユニットとして独立している個々のクラスまたはモジュールをテストしているのでない限り、誰かがそれを「ユニット」または「統合」テストと呼んでもかまいません。たとえば、データ検証クラスの単体テストを行います。データベースインターフェイスの場合、コードの純粋な単体テストはほとんど意味がなく、統合テストのみを実行します。

インプロセスのインメモリデータベースがあると便利ですが、必須ではありません。セットアップコードinitdbsを新しいPostgreSQLにして起動するようにテストハーネスを作成できます。その後、ティアダウンコードはpostmasterを強制終了し、datadirを削除します。これについては this answer で詳しく書きました。

以下も参照してください。

はどうかと言うと:

予想される終了データセットを含むすべてのクエリがPostgressで正常に機能する場合、他のすべてのデータベースで正常に機能すると想定できます

私があなたが正しく言っていることを理解しているなら、そうです、そうです-コードの残りの部分がPostgreSQLのデータセットで動作する場合、それは一般的に別のデータベースからの同じデータを含むデータセットでも同様に機能します。もちろん、データベース固有の機能ではなく、単純なデータ型を使用している限り。

34
Craig Ringer