PostgreSQL
 sql >> Datenbank >  >> RDS >> PostgreSQL

Der H2-Postgresql-Modus scheint bei mir nicht zu funktionieren

Also dachte ich daran, den H2-PosgreSQL-Kompatibilitätsmodus zu verwenden, indem ich dachte, dass alle Postgres-Abfragen auf H2 funktionieren. Bitte korrigieren Sie mich, wenn ich falsch liege

Ich fürchte, das ist nicht wahr.

H2 versucht, die PostgreSQL-Syntax zu emulieren und einige Funktionen und Erweiterungen zu unterstützen. Es wird niemals vollständig dem Verhalten von PostgreSQL entsprechen und unterstützt nicht alle Funktionen.

Die einzigen Optionen, die Sie haben, sind:

  • Verwenden Sie PostgreSQL beim Testen; oder
  • Beenden Sie die Verwendung von Funktionen, die nicht von H2 unterstützt werden

Ich schlage vor, Pg zum Testen zu verwenden. Es ist relativ einfach, eine Testumgebung zu schreiben, die initdb eine Postgres-Instanz ist und sie zum Testen startet und sie danach herunterfährt.

Aktualisierung basierend auf Kommentaren:

Es gibt keine feste Grenze zwischen „Unit“- und „Integration“-Tests. Auch in diesem Fall ist H2 eine externe Komponente. Puristische Unit-Tests hätten einen Dummy-Responder für Abfragen als Teil des Testrahmens. Das Testen gegen H2 ist genauso ein „Integrationstest“ wie das Testen gegen PostgreSQL. Die Tatsache, dass es In-Process und In-Memory ist, ist praktisch, aber funktional nicht signifikant.

Wenn Sie einen Einheitentest durchführen möchten Sie sollten ein weiteres Datenbankziel für Ihre App schreiben, das neben Ihren Zielen „PostgreSQL“, „SybaseIQ“ usw. Nennen Sie es beispielsweise "MockDatabase". Dies sollte nur die erwarteten Ergebnisse von Abfragen zurückgeben. Es führt die Abfragen nicht wirklich aus, es existiert nur, um das Verhalten des restlichen Codes zu testen.

Ich persönlich halte das für eine riesige Zeitverschwendung, aber genau das würde ein Unit-Testing-Purist tun, um die Einführung externer Abhängigkeiten in die Testumgebung zu vermeiden.

Wenn Sie auf Einheitentests (im Gegensatz zu Integrationstests) für Ihre DB-Komponenten bestehen, aber keine Scheinschnittstelle schreiben können/wollen, müssen Sie stattdessen einen Weg finden, eine vorhandene Schnittstelle zu verwenden. H2 wäre dafür ein vernünftiger Kandidat - aber Sie müssen ein neues Backend mit einem neuen Satz von Abfragen schreiben, die für H2 funktionieren, Sie können Ihr PostgreSQL-Backend nicht einfach wiederverwenden. Wie wir bereits festgestellt haben, unterstützt H2 nicht alle Funktionen, die Sie für die Verwendung mit PostgreSQL benötigen, sodass Sie andere Möglichkeiten finden müssen, die gleichen Dinge mit H2 zu tun. Eine Möglichkeit wäre, eine einfache H2-Datenbank mit "erwarteten" Ergebnissen und einfachen Abfragen zu erstellen, die diese Ergebnisse zurückgeben, wobei das Schema der realen Anwendung vollständig ignoriert wird. Der einzige wirkliche Nachteil hier ist, dass die Wartung sehr mühsam sein kann ... aber das ist Unit-Testing.

Persönlich würde ich nur mit PostgreSQL testen. Wenn ich nicht einzelne Klassen oder Module teste, die als klar definierte Einheiten mit schmaler Schnittstelle eigenständig sind, ist es mir egal, ob jemand es einen "Einheits"- oder "Integrations"-Test nennt. Ich werde beispielsweise Datenvalidierungsklassen testen. Für Datenbank-Schnittstellencode macht puristisches Unit-Testing sehr wenig Sinn und ich werde nur Integrationstests durchführen.

Eine In-Process-In-Memory-Datenbank ist dafür zwar bequem, aber nicht erforderlich. Sie können Ihre Testumgebung so schreiben, dass der Setup-Code initdb s ein neues PostgreSQL und startet es; dann beendet der Teardown-Code den Postmaster und löscht das Datadir. Mehr dazu habe ich in dieser Antwort geschrieben.

Siehe auch:

  • PostgreSQL nur im Arbeitsspeicher ausführen

Apropos:

Wenn alle Abfragen mit erwarteten Enddatensätzen in Postgress gut funktionieren, kann ich davon ausgehen, dass es in allen anderen Datenbanken gut funktionieren wird

Wenn ich richtig verstehe, was Sie sagen, dann ja, das ist der Fall - wenn der Rest Ihres Codes mit einem Datensatz aus PostgreSQL funktioniert, sollte es im Allgemeinen genauso mit einem Datensatz funktionieren, der dieselben Daten aus einer anderen Datenbank enthält. Solange es einfache Datentypen verwendet, natürlich keine datenbankspezifischen Funktionen.