13

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();
}

fooServiceOSGi と 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 サービスが依存関係を注入するのを待つか、タイムアウト後に失敗します。

これを完全に理解するのにかなりの時間がかかりました。将来、仲間のプログラマーの頭痛の種が減ることを願っています。

4

5 に答える 5

7

*編集:ソリューション*

この問題をさらに調査した後、私はついに、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テストランナーがそのレースに勝ち、必要なサービスへの参照が注入される前にテストを実行するためです。

この状況を解決するには、JUnitテストを実行して、OSGiランタイムが機能するのを待つ必要があります。テストで必要な依存サービスの数に初期化される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();
}

fooServiceOSGiと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サービスが依存関係を注入するのを待つか、タイムアウト後に失敗します。

これを完全に理解するのにかなりの時間がかかりました。将来、他のプログラマーの頭痛の種を減らすことができるといいのですが。

于 2012-06-12T16:51:19.230 に答える
1

私はあなたが言及した Eclipse ツールに精通していませんが、 Apache Slingでの統合テストにPax Examを使用して成功しています。Maven に精通している場合は、https://svn.apache.org/repos/asf/sling/trunk/installer/it/pom.xml の POM開始に役立つ可能性があります。 https://github.com /tonit/Learn-PaxExamも良い出発点のようです。

Sling テスト ツールは、実行時にバンドルが JUnit テストを OSGi フレームワークに提供できるようにすることで、このコンテキストにも役立ちます。これは、プロジェクトがテストに使用できる実行可能な jar を生成する場合に役立ちます。

于 2011-08-24T07:54:19.947 に答える
1

org.apache.felix.scr.ScrService を取得して、コンポーネントが ACTIVE になるのを積極的に待つほうが、少しすっきりすると思います。このインターフェイスは、equinox と felix の両方で実装されています。

Java ドキュメントAPI の使用法

于 2011-11-08T13:32:32.043 に答える
1

実行構成のタブを使用して設定します。

右クリックして「run as」を選択し、「run configurations...」を選択し、「JUnit Plug-in Test」をダブルクリックして、プラグインタブに依存関係を追加します - 通常のランチャーとほとんど同じです

いくつかのリンク: http://publib.boulder.ibm.com/infocenter/ratdevz/v8r0/index.jsp?topic=/org.eclipse.pde.doc.user/guide/tools/launchers/junit_launcher.htmおよびhttp: //publib.boulder.ibm.com/infocenter/ratdevz/v8r0/index.jsp?topic=/org.eclipse.pde.doc.user/guide/tools/launchers/junit_main.htm

于 2011-08-24T07:55:59.053 に答える
-2

上記のソリューションでは、CountDownLatch は必要ないと思います。

問題は、DS Context 内の JUnit がそれぞれ独自の JUnitTest クラスをインスタンス化することです。最初の DS Context は JUnitTest クラスをインスタンス化し、FooService のバインディング onFooServiceUp を呼び出しますが、この後、JUnit はバインディング メソッド onFooServiceUp を呼び出さずに独自の JUnitTest クラスをインスタンス化します。この場合、FooService は JUnitTest では利用できません。

FooService を static として宣言し (行ったように)、メソッド onFooServiceUp で割り当てる場合、CountDownLatch を使用した構築は必要ありません。

于 2017-01-10T14:42:48.733 に答える