web-dev-qa-db-ja.com

Spring Boot 2.2.2.RELEASEで統合テストの分離が失敗する(SpringBootTestごとにテーブルを削除するときにエラーが発生する)

私たちのアプリは2.0.4リリースで動作しています。 2.2.2.RELEASEにアップグレードすると、統合テストが失敗することがわかります。いくつかの設定ミスがあり、各統合テストがそれ自体をクリーンアップしないか、これまでにない追加の初期化があると思います。私はそれを適切に修正する方法を本当に知りません。

具体的には。各テストは、個別に呼び出すと機能します。これらをすべて実行すると、次のようなエラーが表示されます。

org.hibernate.tool.schema.spi.CommandAcceptanceException: Error executing DDL "drop table somewhere.sometable if exists" via JDBC Statement
...
caused by: org.h2.jdbc.JdbcSQLSyntaxErrorException: Cannot drop "SOME_TABLE" because "FKKJEJC7GUX6OTX5NGANQCMN83R, FK7WLRCFA21PY7CI3R4OL1OWODT, FKQPMY4YOVD3D6HBNT0XX92149P, FK1TG6AMM2NSM6UJTO9EJHPJIXY, FKLPTBKDKFCHE72RJ5RRRIH4ORJ" depends on it; SQL statement:

そして

2019-12-16 21:11:00.075 org.Apache.Tomcat.util.modeler.Registry  : The MBean registry cannot be disabled because it has already been initialised

これは、すでに初期化されているものを再初期化しようとしていることを示唆しています。休止状態の初期化でドロップの順序が間違っています。しかし、私は本当に私たちの側で何も悪いことを見ることができません。いくつかの抜粋を示しましょう:

テストの注釈:

@RunWith(SpringRunner.class)
@ActiveProfiles(...)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class SomeIT {

テストは以下を介して実行されます:

<plugin>
  <groupId>org.Apache.maven.plugins</groupId>
  <artifactId>maven-failsafe-plugin</artifactId>
  <version>2.22.2</version>
  <configuration>
    <useSystemClassLoader>false</useSystemClassLoader>
    <forkCount>0</forkCount>
    <reuseForks>false</reuseForks>
  </configuration>
  <executions>
    <execution>
      <id>integration-test</id>
      <goals>
        <goal>integration-test</goal>
      </goals>
    </execution>
    <execution>
      <id>verify</id>
      <goals>
        <goal>verify</goal>
      </goals>
    </execution>
  </executions>
</plugin>

テストのapplication.properties:

spring.jpa.database=H2
spring.jpa.hibernate.ddl-auto=create
spring.jpa.properties.hibernate.jdbc.batch_size=5
spring.jpa.properties.hibernate.order_inserts=true
spring.jpa.properties.hibernate.order_updates=true
spring.jpa.properties.hibernate.jdbc.batch_versioned_data=true

#this disables option to have opened tx in view IIUC. We don't rely on that, so this just removes warning logging from console.
spring.jpa.open-in-view=false

#used to select db initialization scripts.
spring.datasource.platform=org.hibernate.dialect.H2Dialect

spring.datasource.url=jdbc:h2:mem:somewhere;DB_CLOSE_ON_EXIT=FALSE;DB_CLOSE_DELAY=-1;INIT=create schema if not exists somewhere
spring.datasource.driver-class-name = org.h2.Driver

#this is probably needed for @DataJpaTest: I have no idea how to configure @DataJpaTest so that it can run with
#autoconfigured H2 db, probably it's caused by having schema defined in entities. Anyways @DataJpaTest fails to
#create schema. So alternative is to configure one DB for whole app here, and this option forces all @DataJpaTest not to
#replace this configuration with autoconfigured db.
spring.test.database.replace=none

テストされた変更:

  • 私はcreateをcreate-dropに変更しましたが、それが何らかの方法で役立つ場合は、いいえ、まったく役に立たない場合があります。
  • 私はすべてのITテストのクラスレベルで@DirtiesContextを試してみました。これはとにかく期待することですが、そのコンテキストはすべてのITテストクラスで作成/削除されますが、それも役に立ちませんでした。
  • 私はreplace=noneを削除しようとしましたが、(スキーマが作成されていないため)すべての単体テストが強制終了されるだけで、統合テストにはまったく役立ちません。

現在の回避策:思いついたのは、dbを再利用することだけではありません。 replace=noneを使用した場合、次の方法でのみ可能です。

spring.datasource.url=jdbc:h2:mem:somewhere${random.uuid};DB_CLOSE_ON_EXIT=FALSE;DB_CLOSE_DELAY=-1;INIT=create schema if not exists somewhere

しかし、私はこの「解決策」を深く嫌っています。不適切なデータベースの再初期化、クリーンアップの欠如、またはこれらすべての原因は何ですか?

(編集:この質問に適切なタイトルを知っている場合は、提案してください。ありがとうございます)。

6
Martin Mucha

同じ問題が発生しましたが、残念ながら Melkorの回答 は機能しませんでした。スキーマが複雑すぎて、テーブルを正しい順序でドロップするスクリプトを記述できないからです。

H2は依存関係に関係なく すべてのオブジェクトの削除 をサポートしているため、次のスクリプトはデータベース全体をリセットできます。

src/test/resources/drop-tables.sql

DROP ALL OBJECTS

次に、スクリプトを使用してテーブルを削除するテストプロパティを指定します。

src/test/resources/application.properties

spring.jpa.properties.javax.persistence.schema-generation.drop-source=script
spring.jpa.properties.javax.persistence.schema-generation.drop-script-source=drop-tables.sql
1
hota911

この問題の回避策を見つけたことをお知らせします。 javax.persistenceプロパティでは、スキーマの自動作成の前に実行されるドロップスクリプトを定義できます。

これにより、テーブルを削除する順序を指定できます(最初に依存テーブル)。たぶんこれらをいじってみてください。 spring.jpa.hibernate.ddlプロパティ。

spring.jpa.properties.javax.persistence.schema-generation.database.action=drop-and-create
spring.jpa.properties.javax.persistence.schema-generation.drop-source=script-then-metadata
spring.jpa.properties.javax.persistence.schema-generation.drop-script-source=drop-tables.sql
0
Melkor