TestContainers は、Docker コンテナを使用した自動統合テストをサポートするオープンソースの Java ライブラリです。 本ドキュメントでは、TestContainers を使用して OceanBase Cloud データベースに接続し、使用する方法について説明します。
前提条件
- Docker がダウンロードおよびインストールされ、起動していること。
- IntelliJ IDEA がダウンロードおよびインストールされていること。
- JDK 1.8.0 がダウンロードされていること。
- (オプション)Maven がダウンロードされ、IntelliJ IDEA に設定されていること。
インストール後の確認
Docker が正常にインストールされたかを確認します。
docker -vDocker を手動で起動する必要はありません。後続の手順でサンプルプログラムを実行する際に、Docker は自動的に起動および停止します。
JDK が正常にインストールされたかを確認します。
java -versionMaven が正常にインストールされたかを確認します。
mvn -version(オプション) IntelliJ IDEA での Maven の設定が正しいかを確認します。
本ドキュメントでは、参考として簡単なサンプルプロジェクトのみを提供します。より複雑なサンプルの開発を試みる場合は、開発環境のバージョンに適した Maven をダウンロードし、以下の手順で IntelliJ IDEA で設定を完了してください。
- Maven が正常にインストールされたかを確認します。
mvn -version- IntelliJ 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 の定義があります。
<groupId>を使用して、依存関係が属する組織を指定します。<artifactId>を使用して、依存関係の名前を指定します。<version>を使用して、依存関係のバージョン番号を指定します。<scope>を使用して、依存関係の適用範囲を指定します。つまり、依存関係はテスト時にのみ使用されます。
コードは以下の通りです:
<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 Cloud データベースコンテナを実行するテスト環境を構築し、テストクラスの基本的な設定を定義します。
コードは以下の通りです:
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); }
完全なコードの表示
```java
<?xml version="1.0" encoding="UTF-8"?>
<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>
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 をご参照ください。