JUnitを使用してOSGiでマルチバンドル統合テストを実装する方法を理解しようとしています。JUnitテストのコンテキストでOSGi宣言型サービスを使用する
統合テストでは、バンドルのサブセットをインスタンス化して、そのサブシステム内の機能を自動的に検証します。
私たちはEquinoxを実行しており、ツールチェーンとしてEclipseを使用しています。 EclipseはOSGiフレームワークを起動してバンドルをインスタンス化する "JUnitプラグインとして実行"オプションを提供しています。これは後続のパスだと思いますが、DS参照をテストに挿入する方法は見つけられません。 ServiceTrackerをさまざまなサービスバンドルにアクセスするためのプログラム的手段として使用していますが、それはDSを使用する目的よりも優れていますか?
OSGIを使い始めたばかりなので、マルチバンドルテストを一緒にするパズルの一部が欠落しているだけです。
アイデア?
ありがとう、ジェラード。
* EDIT:
の場合:SOLUTION *
この問題にさらに見た後、私は最終的にJUnitのプラグイン機能を使用して所定の位置にこのMULT-バンドル統合テストを配置する方法を考え出しました動的なサービスインジェクションを動作させるには、通常、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を使用して解決しました。 すべての依存性注入メソッドがカウントダウンされ、それらがすべて完了すると、テストが開始されます。 fooService
参照がOSGiのとJUnitの実行コンテキスト間でサービス参照を共有できるように静的である必要が
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();
}
注:コードは、このようになります。 CountDownLatchは、この共有参照を安全に発行するための高レベルの同期メカニズムを提供します。JUnitフレームワークは依存性を注入するためのOSGi DSサービスを待つか、タイムアウト後に失敗
@Before
public void dependencyCheck() {
// Wait for OSGi dependencies
try {
dependencyLatch.await(10, TimeUnit.SECONDS);
// Dependencies fulfilled
} catch (InterruptedException ex) {
fail("OSGi dependencies unfulfilled");
}
}
この方法:
そして、依存性チェックは、テスト実行の前に添加されるべきです。
これを完全に理解するまでにかなりの時間がかかりました。私はそれが将来、仲間のプログラマーに頭を悩ませてくれることを願っています。
これは私が言及した「JUnitプラグインとして実行」オプションですが、宣言型サービスを注入するのには十分ではないようです。つまり、どこにバインディングメソッドを宣言しますか?文脈についての質問もあります。 Junitの状況で注入が行われるのでしょうか?もしそうなら、その仕組みはどのように機能していますか? – maasg
アプリケーションでDSを使用するのと同じです。 DSバンドルを追加する必要があります。これは、ロードされている他のバンドルをスキャンして配線を管理します。 DSバインディングは、バンドルのjar内のOSGI-INFのコンポーネントxmlで宣言されます。 Eclipse PluginプロジェクトでDSを使用する方法については、http://www.vogella.de/articles/OSGi/article.html#declarativeservices_runを参照してください。 HTH – earcam
提案していただきありがとうございます。 DS注入メソッドは、Junit-Pluginの実行のコンテキストで呼び出されることはありません。私のOSG-INFはそれらを正しく宣言します。 – maasg