JUnit を使用して OSGi でマルチバンドル統合テストを実装する方法を理解しようとしています。
統合テストとは、バンドルのサブセットをインスタンス化して、そのサブシステムの機能を自動的に検証することを意味します。
Equinox を実行し、ツールチェーンとして Eclipse を使用しています。Eclipse は、OSGi フレームワークを起動し、configures バンドルをインスタンス化する「Run as JUnit Plug-in」オプションを提供しているため、これが従うべきパスだと思いますが、DS 参照をテストに挿入する方法が見つかりません。さまざまなサービス バンドルにアクセスするためのプログラムによる手段として ServiceTracker を使用しているのを見てきましたが、それは DS を使用する目的よりも優れていますね。
私は OSGI を使い始めたばかりなので、マルチバンドル テストをまとめるためのパズルのピースが欠けているだけだと思います。
何か案は?
ありがとう、ジェラルド。
*編集:解決策*
この問題をさらに詳しく調べた結果、JUnit プラグイン機能を使用して、このマルチバンドル統合テストを配置する方法を最終的に見つけました。
動的サービス インジェクションを機能させるには、DS を使用するときに通常行われるように、インジェクトされた依存関係を宣言する必要があるサービス定義ファイルを作成する必要があります。このファイルは (通常)OSGI-INF/
ディレクトリの下にあります。例えばOSGI-INF/service.xml
service.xml は、このテストに必要な依存関係を宣言する必要がありますが、独自のサービスは提供しません。
service.xml
<?xml version="1.0" encoding="UTF-8"?>
<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" immediate="true" name="MyTest" activate="startup" deactivate="shutdown">
<implementation class="com.test.functionaltest.MyTester"/>
<reference name="OtherService" interface="com.product.service.FooService" policy="static" cardinality="1..1" bind="onServiceUp" unbind="onServiceDown"/>
</scr:component>
これにより、宣言された onServiceUp メソッドを使用して FooService への依存関係を挿入するよう DS に指示されます。onServiceDown は、テスト実行後の OSGi シャットダウン フェーズ中に呼び出されるので、実装する必要があります。
com.test.functionaltest.MyTester には、典型的な JUnit プラクティスに従って実行されるテスト メソッドが含まれています。
ここまでは、すべて「本による」です。それでも、Junit が実行されると、FooService への参照にアクセスするときに NullPointerException がスローされます。その理由は、OSGi フレームワークが JUnit テスト ランナー コンテキストと競合状態にあり、通常は Junit テスト ランナーがその競合に勝ち、必要なサービスへの参照が挿入される前にテストを実行するためです。
この状況を解決するには、OSGi ランタイムがその作業を行うまで Junit テストを待機させる必要があります。テストで必要な依存サービスの数に初期化される CountDownLatch を使用して、この問題に対処しました。次に、すべての依存性注入メソッドがカウントダウンし、すべてが完了すると、テストが開始されます。コードは次のようになります。
private static CountDownLatch dependencyLatch = new CountDownLatch(1);// 1 = number of dependencies required
static FooService fooService = null;
public void onFooServiceUp(FooService service) {
fooService = service;
dependencyLatch.countDown();
}
fooService
OSGi と JUnit の実行コンテキスト間でサービス参照を共有できるようにするには、参照を静的にする必要があることに注意してください。CountDownLatch は、この共有参照を安全に発行するための高レベルの同期メカニズムを提供します。
次に、テスト実行前に依存関係チェックを追加する必要があります。
@Before
public void dependencyCheck() {
// Wait for OSGi dependencies
try {
dependencyLatch.await(10, TimeUnit.SECONDS);
// Dependencies fulfilled
} catch (InterruptedException ex) {
fail("OSGi dependencies unfulfilled");
}
}
このようにして、Junit フレームワークは OSGi DS サービスが依存関係を注入するのを待つか、タイムアウト後に失敗します。
これを完全に理解するのにかなりの時間がかかりました。将来、仲間のプログラマーの頭痛の種が減ることを願っています。