web-dev-qa-db-ja.com

Spring Bootテスト用の組み込みPostgres

データベース移行にFlywayを使用して、Postgresが支援するSpring Bootアプリを作成しています。私は、Postgresと組み込み単体テストデータベースの両方で望ましい結果を生成する移行を作成できないという問題にぶつかりました(Postgres互換モードが有効になっている場合でも)。だから、私は単体テストに埋め込みPostgresを使用することを検討しています。

埋め込まれたpostgres 実装に出くわしましたが、Spring Bootの単体テストフレームワーク(Spring Dataリポジトリのテスト用)内でのみ実行するように設定する方法がわかりません。前述のツールまたは代替の埋め込みバージョンのPostgresを使用して、これをどのように設定しますか?

15
SingleShot

私は、@ MartinVolejnikが言及した embedded-database-spring-test ライブラリの作成者です。ライブラリはすべてのニーズを満たす必要があると思います(PostgreSQL + Spring Boot + Flyway +統合テスト)。問題が発生していることを本当に申し訳ありません。そこで、Spring Bootフレームワークと一緒にライブラリを使用する方法を示す simple demo app を作成しました。以下に、必要な基本手順をまとめました。

Maven構成

次のMaven依存関係を追加します。

<dependency>
    <groupId>io.zonky.test</groupId>
    <artifactId>embedded-database-spring-test</artifactId>
    <version>1.5.0</version>
    <scope>test</scope>
</dependency>

フライウェイ構成

次のプロパティをアプリケーション構成に追加します。

# Sets the schemas managed by Flyway -> change the xxx value to the name of your schema
# flyway.schemas=xxx // for spring boot 1.x.x
spring.flyway.schemas=xxx // for spring boot 2.x.x

さらに、org.flywaydb.test.junit.FlywayTestExecutionListenerを使用しないようにしてください。ライブラリにはデータベースの初期化を最適化できる独自のテスト実行リスナーがあり、FlywayTestExecutionListenerが適用されている場合、この最適化は効果がないためです。

Spring Boot 2の設定

Spring Boot 2以降、HibernateおよびPostgresドライバーとの互換性の問題があります。そのため、次のプロパティをアプリケーション構成に追加して修正する必要がある場合があります。

# Workaround for a compatibility issue of Spring Boot 2 with Hibernate and Postgres Driver
# See https://github.com/spring-projects/spring-boot/issues/12007
spring.jpa.properties.hibernate.jdbc.lob.non_contextual_creation=true

組み込みデータベースの使用を示すテストクラスの例:

@RunWith(SpringRunner.class)
@DataJpaTest
@AutoConfigureEmbeddedDatabase
public class SpringDataJpaAnnotationTest {

    @Autowired
    private PersonRepository personRepository;

    @Test
    public void testEmbeddedDatabase() {
        Optional<Person> personOptional = personRepository.findById(1L);

        assertThat(personOptional).hasValueSatisfying(person -> {
            assertThat(person.getId()).isNotNull();
            assertThat(person.getFirstName()).isEqualTo("Dave");
            assertThat(person.getLastName()).isEqualTo("Syer");
        });
    }
}
21
Tomáš Vaněk

以下の設定は、Spring Boot 2.0でうまく機能します。

embedded-database-spring-test に対する利点は、このソリューションがフライウェイをクラスパスにプッシュしないことであり、Spring Bootの自動構成を台無しにする可能性があります。

@Configuration
@Slf4j
public class EmbeddedPostgresConfiguration {

    @Bean(destroyMethod = "stop")
    public PostgresProcess postgresProcess() throws IOException {
        log.info("Starting embedded Postgres");

        String tempDir = System.getProperty("Java.io.tmpdir");
        String dataDir = tempDir + "/database_for_tests";
        String binariesDir = System.getProperty("Java.io.tmpdir") + "/postgres_binaries";

        PostgresConfig postgresConfig = new PostgresConfig(
                Version.V10_3,
                new AbstractPostgresConfig.Net("localhost", Network.getFreeServerPort()),
                new AbstractPostgresConfig.Storage("database_for_tests", dataDir),
                new AbstractPostgresConfig.Timeout(60_000),
                new AbstractPostgresConfig.Credentials("bob", "ninja")
        );

        PostgresStarter<PostgresExecutable, PostgresProcess> runtime =
                PostgresStarter.getInstance(EmbeddedPostgres.cachedRuntimeConfig(Paths.get(binariesDir)));
        PostgresExecutable exec = runtime.prepare(postgresConfig);
        PostgresProcess process = exec.start();

        return process;
    }

    @Bean(destroyMethod = "close")
    @DependsOn("postgresProcess")
    DataSource dataSource(PostgresProcess postgresProcess) {
        PostgresConfig postgresConfig = postgresProcess.getConfig();

        val config = new HikariConfig();
        config.setUsername(postgresConfig.credentials().username());
        config.setPassword(postgresConfig.credentials().password());
        config.setJdbcUrl("jdbc:postgresql://localhost:" + postgresConfig.net().port() + "/" + postgresConfig.storage().dbName());

        return new HikariDataSource(config);
    }
}

Maven:

        <dependency>
            <groupId>ru.yandex.qatools.embed</groupId>
            <artifactId>postgresql-embedded</artifactId>
            <version>2.9</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.postgresql</groupId>
            <artifactId>postgresql</artifactId>
        </dependency>

クラスは、私がここで見つけたコードに基づいています: https://github.com/nkoder/postgresql-embedded-example

適切な接続プーリングにHikariDatasource(Spring Bootのデフォルト)を使用するように変更しました。 binariesDirdataDirは、反復テストでの高価な抽出+ initdbを避けるために使用されます。

2
Mateusz Stefek

これを見てください: https://github.com/zonkyio/embedded-database-spring-test 。明確にするために、これは統合テスト用です。 Springコンテキストの意味は、個々のテスト中に初期化されます。

ツールのドキュメントに従って、あなたがする必要があるのは、クラスの上に_@AutoConfigureEmbeddedDatabase_アノテーションを置くことだけです:

_@RunWith(SpringRunner.class)
@AutoConfigureEmbeddedDatabase
@ContextConfiguration("/path/to/app-config.xml")
public class FlywayMigrationIntegrationTest {

    @Test
    @FlywayTest(locationsForMigrate = "test/db/migration")
    public void testMethod() {
        // method body...
    }
}
_

maven依存関係を追加します。

_<dependency>
  <groupId>io.zonky.test</groupId>
  <artifactId>embedded-database-spring-test</artifactId>
  <version>1.1.0</version>
  <scope>test</scope>
</dependency>
_

_@DataJpaTest_とともに使用するには、注釈@AutoConfigureTestDatabase(replace = NONE)を使用してデフォルトのテストデータベースを無効にする必要があります。

_@RunWith(SpringRunner.class)
@AutoConfigureTestDatabase(replace = NONE)
@AutoConfigureEmbeddedDatabase
@DataJpaTest
public class SpringDataJpaTest {
// class body...
}
_

より使いやすくするために、次のような複合アノテーションを作成することもできます。

_@Documented
@Inherited
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@AutoConfigureTestDatabase(replace = NONE)
@AutoConfigureEmbeddedDatabase
@DataJpaTest
public @interface PostgresDataJpaTest {
}
_

..そしてそれをテストクラスの上で使用します:

_@RunWith(SpringRunner.class)
@PostgresDataJpaTest // custom composite annotation
public class SpringDataJpaTest {
// class body...
}
_
1
Martin Volejnik

https://github.com/TouK/dockds を試すことができます。これにより、Dockerに含まれるデータベースが自動構成されます。

0
Tomasz Wielga