1. 概要

通常、JNDIを使用するアプリケーションをテストする場合、実際のデータソースではなく、モックされたデータソースを使用したい場合があります。 これは、単体テストを単純にし、外部コンテキストから完全に分離するためにテストする場合の一般的な方法です。

このチュートリアルでは、SpringフレームワークとSimple-JNDIライブラリを使用して模擬JNDIデータソースをテストする方法を紹介します。

このチュートリアルでは、単体テストのみに焦点を当てます。 ただし、JPAとJNDIデータソースを使用してSpringアプリケーションを作成する方法に関する記事を必ず確認してください。

2. クイックJNDI要約

つまり、 JNDI は、データベース接続などの外部リソースに論理名をバインドします。 主なアイデアは、アプリケーションがJNDI名を除いて、定義されたデータソースについて何も知る必要がないということです。

簡単に言うと、すべてのネーミング操作はコンテキストに関連しているため、JNDIを使用してネーミングサービスにアクセスするには、最初にInitialContextオブジェクトを作成する必要があります。 名前が示すように、 InitialContext クラスは、名前付け操作の開始点を提供する初期(ルート)コンテキストをカプセル化します。

簡単に言うと、ルートコンテキストはエントリポイントとして機能します。 これがないと、JNDIはリソースをバインドまたはルックアップできません。

3. SpringでJNDIデータソースをテストする方法

Springは、SimpleNamingContextBuilderを介してJNDIとのすぐに使用可能な統合を提供します。 このヘルパークラスは、テスト目的でJNDI環境をモックするための優れた方法を提供します。

それでは、SimpleNamingContextBuilderクラスを使用してJNDIデータソースを単体テストする方法を見てみましょう。

まず、データソースオブジェクトをバインドおよび取得するための初期命名コンテキストを構築する必要があります。

@BeforeEach
public void init() throws Exception {
    SimpleNamingContextBuilder.emptyActivatedContextBuilder();
    this.initContext = new InitialContext();
}

emptyActivatedContextBuilder()メソッドを使用してルートコンテキストを作成しました。これは、新しいビルダーを作成したり、既存のビルダーを返したりするため、コンストラクターよりも柔軟性が高いためです。

コンテキストができたので、単体テストを実装して、JNDIを使用してJDBC DataSourceオブジェクトを格納および取得する方法を確認しましょう。

@Test
public void whenMockJndiDataSource_thenReturnJndiDataSource() throws Exception {
    this.initContext.bind("java:comp/env/jdbc/datasource", 
      new DriverManagerDataSource("jdbc:h2:mem:testdb"));
    DataSource ds = (DataSource) this.initContext.lookup("java:comp/env/jdbc/datasource");

    assertNotNull(ds.getConnection());
}

を見るとわかるように、 bind()メソッドを使用して、JDBC DataSourceオブジェクトを名前java:comp / env /jdbc/にマップします。データソース

次に、 lookup()メソッドを使用して、JDBC DataSource オブジェクトをバインドするために以前に使用した正確な論理名を使用して、JNDIコンテキストからDataSource参照を取得します。 。

指定されたオブジェクトがコンテキストで見つからない場合、JNDIは単に例外をスローすることに注意してください。

SimpleNamingContextBuilder クラスは、Spring 5.2以降、Simple-JNDI などの他のソリューションを優先して、非推奨になっていることに注意してください。

4. Simple-JNDIを使用したJNDIデータソースのモックとテスト

Simple-JNDIを使用すると、プロパティファイルで定義されたオブジェクトをモックされたJNDI環境にバインドできます。 JavaEEコンテナの外部のJNDIからタイプjavax.sql.DataSourceのオブジェクトを取得するための優れたサポートが付属しています。

それでは、それをどのように使用できるかを見てみましょうまず、Simple-JNDI依存関係をpom.xmlに追加する必要があります。

<dependency>
    <groupId>com.github.h-thurow</groupId>
    <artifactId>simple-jndi</artifactId>
    <version>0.23.0</version>
</dependency>

Simple-JNDIライブラリの最新バージョンは、 MavenCentralにあります。

次に、JNDIコンテキストを設定するために必要なすべての詳細を使用してSimple-JNDIを構成します。 そのためには、クラスパスに配置する必要のあるjndi.propertiesファイルを作成する必要があります。

java.naming.factory.initial=org.osjava.sj.SimpleContextFactory
org.osjava.sj.jndi.shared=true
org.osjava.sj.delimiter=.
jndi.syntax.separator=/
org.osjava.sj.space=java:/comp/env
org.osjava.sj.root=src/main/resources/jndi

java.naming.factory.initial は、初期コンテキストの作成に使用されるコンテキストファクトリクラスを指定します。

org.osjava.sj.jndi.shared = true は、すべてのInitialContextオブジェクトが同じメモリを共有することを意味します。

ご覧のとおり、 org.osjava.sj.space プロパティを使用して、 java:/ comp /envをすべてのJNDIルックアップの開始点として定義しました。

org.osjava.sj.delimiterプロパティとjndi.syntax.separatorプロパティの両方を使用する背後にある基本的な考え方は、ENCの問題を回避することです。

org.osjava.sj.root プロパティを使用すると、プロパティファイルが保存される場所へのパスを定義できます。 この場合、すべてのファイルは src / main / resources /jndiフォルダーの下にあります。

それでは、datasource.propertiesファイル内にjavax.sql.DataSourceオブジェクトを定義しましょう。

ds.type=javax.sql.DataSource
ds.driver=org.h2.Driver
ds.url=jdbc:jdbc:h2:mem:testdb
ds.user=sa
ds.password=password

それでは、単体テスト用のInitialContextオブジェクトを作成しましょう。

@BeforeEach
public void setup() throws Exception {
    this.initContext = new InitialContext();
}

最後に、単体テストケースを実装して、datasource.propertiesファイルですでに定義されているDataSourceオブジェクトを取得します。

@Test
public void whenMockJndiDataSource_thenReturnJndiDataSource() throws Exception {
    String dsString = "org.h2.Driver::::jdbc:jdbc:h2:mem:testdb::::sa";
    Context envContext = (Context) this.initContext.lookup("java:/comp/env");
    DataSource ds = (DataSource) envContext.lookup("datasource/ds");

    assertEquals(dsString, ds.toString());
}

5. 結論

このチュートリアルでは、J2EEコンテナの外部でJNDIをテストするという課題に取り組む方法を説明しました。 SpringFrameworkとSimple-JNDIライブラリを使用して模擬JNDIデータソースをテストする方法を確認しました。

いつものように、コードはGitHubから入手できます。