TestContainersは、Dockerコンテナを使用して自動化された統合テストをサポートする、オープンソースのJavaライブラリです。 本記事では、TestContainersを使用してOceanBaseデータベースに接続し、使用する方法について説明します。
前提条件
- Docker をダウンロードして、インストールし、起動済みであること。
- IntelliJ IDEA をダウンロードしてインストール済みであること。
- JDK 1.8.0がダウンロード済みであること。
- (オプション)IntelliJ IDEAをダウンロードして Maven を設定済みであること。
インストール後の確認
Dockerが正常にインストールされたかどうか確認します:
docker -vDockerを手動で起動する必要はありません。後続の手順でサンプルプログラムを実行すると、自動的にDockerが起動または停止します。
JDKが正常にインストールされたかどうか確認します:
java -versionMavenが正常にインストールされているかどうか確認します:
mvn -version(オプション)IntelliJ IDEAのMavenの設定が正しいかどうか確認します:
本記事は、参考用の簡単なサンプルプロジェクトを提供しています。より複雑なサンプルの開発を試したい場合は、開発環境に適したバージョンのMavenをダウンロードし、以下の手順に従ってIntelliJ IDEAに設定することができます。
Mavenが正常にインストールされているかどうか確認します:
mvn -versionIntelliJ IDEAを開き、IntelliJ IDEA > Settings > Build,Execution,Development > Build Tools > Maven をクリックし、Maven Home path に Maven インストールパッケージのパスを設定します。

操作手順
- ダウンロードしたプロジェクトのサンプルコードを解凍し、IDEAを使用してプロジェクトのサンプルコードを開きます。
- パス src > test > java 内にあるプロジェクトサンプル ExampleTest を実行します。
- 以下のような結果が返された場合、データベース接続が成功し、サンプルプロジェクトが正しく実行されたことを示します。
...
53575 [main] INFO com.oceanbase.example.ExampleTest - Connect to OceanBase docker container successfully.
53577 [main] INFO com.oceanbase.example.ExampleTest - Prepare database and table.
53892 [main] INFO com.oceanbase.example.ExampleTest - Insert data to table `testcontainers`.`person`.
53928 [main] INFO com.oceanbase.example.ExampleTest - Query rows from `testcontainers`.`person`.
53932 [main] INFO com.oceanbase.example.ExampleTest - Row 0: name Adam, age 28.
53932 [main] INFO com.oceanbase.example.ExampleTest - Row 1: name Eve, age 26.
プロジェクトコードについて
Testcontainers をクリックしてプロジェクトコードをダウンロードします。これは TestcontainersDemo.zip という名前の圧縮ファイルです。
解凍すると、TestcontainersDemoという名前のディレクトリが作成されます。ディレクトリ構造は以下のとおりです:
JDBCDemo
├── src
│ └── test
│ └── java
│ └── ExampleTest.java
└── pom.xml
ファイルの説明:
src:ソースコードのルートディレクトリです。test:アプリケーションの主要なロジックを含む、メインコードディレクトリです。java:Javaソースコードディレクトリです。ExampleTest.java:メインクラス。テーブルの作成やデータの挿入などのロジックを含みます。pom.xml:プロジェクトの依存関係とビルド設定を管理するために使用されるMavenプロジェクトの設定ファイルです。
pom.xmlコードの紹介
pom.xml ファイルはMavenプロジェクトの設定ファイルで、プロジェクトの依存関係、プラグイン、ビルドルールなどの情報を定義しています。MavenはJavaプロジェクト管理ツールで、依存関係のダウンロード、プロジェクトのコンパイル、パッケージングなどの操作を自動化できます。
本記事の pom.xml ファイルのコードは、主に以下のいくつかの部分が含まれます:
ファイル宣言ステートメントです。
このファイルがXMLファイルであり、使用しているXMLのバージョンが
1.0で、文字エンコーディング方式がUTF-8であることを宣言しています。コード:
<?xml version="1.0" encoding="UTF-8"?>POMのネームスペースとPOMモデルのバージョンを設定します。
xmlnsを使用して、POMのネームスペースをhttp://maven.apache.org/POM/4.0.0と指定します。xmlns:xsiを使用して、XMLネームスペースをhttp://www.w3.org/2001/XMLSchema-instanceと指定します。xsi:schemaLocationを使用して、POMのネームスペースをhttp://maven.apache.org/POM/4.0.0、POMのXSDファイルの場所をhttp://maven.apache.org/xsd/maven-4.0.0.xsdと指定します。<modelVersion>要素を使用して、このPOMファイルで使用されるPOMモデルバージョンを4.0.0と指定します。
コード:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <!-- その他の設定 --> </project>基本情報を設定します。
<groupId>を使用して、プロジェクトが属する組織をcom.exampleと指定します。<artifactId>を使用して、プロジェクトの名前をJDBCDemoと指定します。<version>を使用して、プロジェクトのバージョン番号を1.0-SNAPSHOTと指定します。
コード:
<groupId>org.example</groupId> <artifactId>JDBCDemo</artifactId> <version>1.0-SNAPSHOT</version>プロジェクトが依存する外部パッケージを設定します。それぞれにgroupId、artifactId、およびversionの定義があります。
1. `<groupId>` を使用して、依存関係が所属する組織を指定します。 2. `<artifactId>` を使用して、依存関係の名前を指定します。 3. `<version>` を使用して、依存関係のバージョンを指定します。 4. `<scope>` を使用して依存関係の範囲を指定します。その依存関係はテスト時のみ使用されます。 **コード:** ```java <dependencies> <dependency> //MySQLのJDBCを使用している場合は、ここにあるgroupId、artifactId、versionの情報を置き換える必要があります。 <groupId>com.oceanbase</groupId> <artifactId>oceanbase-client</artifactId> <version>2.4.9</version> </dependency> <dependency> <groupId>org.testcontainers</groupId> <artifactId>oceanbase</artifactId> <version>1.19.7</version> <scope>test</scope> </dependency> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-slf4j-impl</artifactId> <version>2.17.1</version> <scope>test</scope> </dependency> </dependencies> ```
ExampleTest.javaコードの紹介
ExampleTest.java ファイルはサンプルプログラムの一部であり、TestcontainersフレームワークとJUnitを使用してテスト用のJavaクラスを作成します。
Testcontainersを使用してOceanBaseデータベースコンテナを実行するテスト環境を構築し、いくつかのテストクラスの基本設定を定義しました。
コード:
import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; // テストクラスの定義を開始する public class ExampleTest { // SLF4J Loggerのインスタンスを生成し、ExampleTestクラスのログを記録する private static final Logger LOG = LoggerFactory.getLogger(ExampleTest.class); // OceanBaseコンテナのインスタンスを作成して、指定のDockerイメージを使用し、環境変数を設定する public static final OceanBaseCEContainer CONTAINER = new OceanBaseCEContainer("oceanbase/oceanbase-ce:4.2.2") .withEnv("MODE", "slim") // 環境変数MODEをslimに設定する .withEnv("FASTBOOT", "true") // 環境変数FASTBOOTをtrueに設定する .withLogConsumer(new Slf4jLogConsumer(LOG)); // ログコンシューマーを追加し、SLF4Jを使用してコンテナログを記録する // すべてのテストが開始される前にこのメソッドを実行して、環境準備を実行する @BeforeClass public static void startContainers() { // 非同期にCONTAINERを起動し、起動が完了するのを待機する Startables.deepStart(Stream.of(CONTAINER)).join(); // Dockerイメージ名、コンテナホストアドレス、マッピングポートを含む、コンテナの起動に関する情報を出力する LOG.info( "OceanBase docker container started, image: {}, host: {}, sql port: {}, rpc port:{}.", CONTAINER.getDockerImageName(), CONTAINER.getHost(), CONTAINER.getMappedPort(2881), CONTAINER.getMappedPort(2882)); } // すべてのテストが終了した後にこのメソッドを実行し、リソースのクリーンアップを実行する @AfterClass public static void closeContainers() { // コンテナをクローズする CONTAINER.close(); // コンテナ停止ログをレコードする LOG.info("OceanBase docker container stopped."); } ```テストロジックを作成します。
コード:
// データベースの追加と検索操作のテスト @Test public void test() { // データベースとテーブルの名前 String database = "testcontainers"; String table = "person"; // データベースとテーブルの完全な名前をフォーマットし、バッククォート(`)を使用してSQLキーワードの競合を防止する String tableName = String.format("`%s`.`%s`", database, table); // OceanBaseコンテナへの接続試行をログに出力する LOG.info( "Try to connect to OceanBase docker container with url: {}.", CONTAINER.getJdbcUrl()); // OceanBaseコンテナとのデータベース接続を作成する try (Connection connection = CONTAINER.createConnection("?useSSL=false")) { LOG.info("Connect to OceanBase docker container successfully."); LOG.info("Prepare database and table.");テーブルを作成します。
コード:
// データベースとテーブルを作成する try (Statement statement = connection.createStatement()) { statement.execute("CREATE DATABASE IF NOT EXISTS " + database); statement.execute("USE " + database); statement.execute( "CREATE TABLE IF NOT EXISTS " + table + " (name VARCHAR(50), age INT)"); } catch (SQLException e) { throw new RuntimeException(e); }データを挿入します。
コード:
LOG.info("Insert data to table {}.", tableName); try (PreparedStatement ps = connection.prepareStatement("INSERT INTO " + tableName + " values(?, ?)")) { ps.setString(1, "Adam"); ps.setInt(2, 28); ps.executeUpdate(); ps.setString(1, "Eve"); ps.setInt(2, 26); ps.executeUpdate(); }データを検索します。
コード:
LOG.info("Query rows from {}.", tableName); try (PreparedStatement ps = connection.prepareStatement( "SELECT * from " + tableName, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY)) { ResultSet rs = ps.executeQuery(); int count = 0; while (rs.next()) { LOG.info("Row {}: name {}, age {}.", count++, rs.getString(1), rs.getInt(2)); }例外処理を行います。
上記のデータベース操作を実行する過程で例外が発生した場合、これらの例外はキャプチャされ、エラーメッセージとスタックトレースの詳細が出力されます。
コード:
} catch (SQLException e) { // 異常が発生した場合、ランタイム例外を再スローする throw new RuntimeException(e); }
全コード表示
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.oceanbase.example</groupId>
<artifactId>testcontainers-java</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>com.oceanbase</groupId>
<artifactId>oceanbase-client</artifactId>
<version>2.4.9</version>
</dependency>
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>oceanbase</artifactId>
<version>1.19.7</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j-impl</artifactId>
<version>2.17.1</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
package com.oceanbase.example;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.testcontainers.containers.output.Slf4jLogConsumer;
import org.testcontainers.lifecycle.Startables;
import org.testcontainers.oceanbase.OceanBaseCEContainer;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.stream.Stream;
public class ExampleTest {
private static final Logger LOG = LoggerFactory.getLogger(ExampleTest.class);
public static final OceanBaseCEContainer CONTAINER =
new OceanBaseCEContainer("oceanbase/oceanbase-ce:4.2.2")
.withEnv("MODE", "slim")
.withEnv("FASTBOOT", "true")
.withLogConsumer(new Slf4jLogConsumer(LOG));
@BeforeClass
public static void startContainers() {
Startables.deepStart(Stream.of(CONTAINER)).join();
LOG.info(
"OceanBase docker container started, image: {}, host: {}, sql port: {}, rpc port:{}.",
CONTAINER.getDockerImageName(),
CONTAINER.getHost(),
CONTAINER.getMappedPort(2881),
CONTAINER.getMappedPort(2882));
}
@AfterClass
public static void closeContainers() {
CONTAINER.close();
LOG.info("OceanBase docker container stopped.");
}
@Test
public void test() {
String database = "testcontainers";
String table = "person";
String tableName = String.format("`%s`.`%s`", database, table);
LOG.info(
"Try to connect to OceanBase docker container with url: {}.",
CONTAINER.getJdbcUrl());
try (Connection connection = CONTAINER.createConnection("?useSSL=false")) {
LOG.info("Connect to OceanBase docker container successfully.");
LOG.info("Prepare database and table.");
try (Statement statement = connection.createStatement()) {
statement.execute("CREATE DATABASE IF NOT EXISTS " + database);
statement.execute("USE " + database);
statement.execute(
"CREATE TABLE IF NOT EXISTS " + table + " (name VARCHAR(50), age INT)");
} catch (SQLException e) {
throw new RuntimeException(e);
}
LOG.info("Insert data to table {}.", tableName);
try (PreparedStatement ps =
connection.prepareStatement("INSERT INTO " + tableName + " values(?, ?)")) {
ps.setString(1, "Adam");
ps.setInt(2, 28);
ps.executeUpdate();
ps.setString(1, "Eve");
ps.setInt(2, 26);
ps.executeUpdate();
}
LOG.info("Query rows from {}.", tableName);
try (PreparedStatement ps =
connection.prepareStatement(
"SELECT * from " + tableName,
ResultSet.TYPE_FORWARD_ONLY,
ResultSet.CONCUR_READ_ONLY)) {
ResultSet rs = ps.executeQuery();
int count = 0;
while (rs.next()) {
LOG.info("Row {}: name {}, age {}.", count++, rs.getString(1), rs.getInt(2));
}
assert count == 2;
}
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
}
関連ドキュメント
- Testcontainers for Java公式ドキュメント
- OceanBaseのDockerイメージを使用するには、GenericContainerを使用する必要があります。ドキュメント OceanBase Moduleを参照してください。
クリックしてTestcontainersDemoサンプルプロジェクトをダウンロード