1

プロジェクトで liferay サービス ビルダーを使用していますが、*Util クラスをテストしたいと考えています。それは簡単ですが、初期化環境の簡単な方法がわかりません。たとえば、service.xml (自動生成) からのスプリング構成を使用したアリ テストでは、init Bean に InitUtil.initWithSpring() を使用しますが、次のエラーが発生します。

[junit] Tests run: 1, Failures: 0, Errors: 1, Time elapsed: 2,413 sec
[junit] Tests run: 1, Failures: 0, Errors: 1, Time elapsed: 2,413 sec
[junit] 
[junit] Testcase: testJournalArticleSearch(MTest):  Caused an ERROR
[junit] BeanLocator has not been set for servlet context My-portlet
[junit] com.liferay.portal.kernel.bean.BeanLocatorException: BeanLocator has not been set for servlet context My-portlet
[junit]     at com.liferay.portal.kernel.bean.PortletBeanLocatorUtil.locate(PortletBeanLocatorUtil.java:42)
[junit]     at com.my.service.EntityLocalServiceUtil.getService(EntityLocalServiceUtil.java:70)
[junit]     at MTest.setUp(MTest.java:21)

この問題に関するいくつかの記事を見たことがありますが、うまくいかないか、これらの記事を理解できません... 誰かがこの問題の簡単な解決策を知っていますか?

4

2 に答える 2

3

私はこれを答えとして書いています-それはもっとコメントになるでしょうが、フォーマットオプションと答えの長さは私が求めているものです。

生成されたコードの単体テストを作成する際に問題が発生することがよくあります。*Utilは、servicebuilderと一緒に使用すると、生成されたコード(* LocalServiceUtil)のように聞こえます。

私のアドバイスは、* LocalServiceImplコードをテストし、コードジェネレーターが正しいことを信頼することです(または、コードジェネレーターのテストで間違いが検出されることを信頼しますが、これは範囲外です)。結局のところ、servicebuilderの* LocalServiceUtilクラスが提供する機能は、(Spring構成に基づいて)正しい実装を検索してそれに委任する間接参照です。*LocalServiceUtilクラスにはビジネスロジックはありません。これは*LocalServiceImplクラスにあります。

次のポイントは次のとおりです。*Implクラスでさえ、モックする必要がある他のサービスにアクセスするため、テストが難しい場合があります。この場合、単体テストを読み取り可能でデータベースから独立させておくために、他のサービスにアクセスしないコードのレイヤーをテストすることを提案しています。この回答から盗んだコードを選択するために、方程式からUserLocalServiceを除外して、テストする方法を次に示します(注意:擬似コード、コンパイラーを見たことがない、この入力フィールドで編集しています)

テストしようとしているコードは次のとおりです。

class MyUserUtil {
  public static boolean isUserFullAge(User user)  {
    Date birthday = user.getBirthday();
    long years = (System.currentTimeMillis() - birthday.getTime()) / ((long)365*24*60*60*1000);
    return years >= 18;
  }
}

これに対する私のテストは、UserLocalServiceを除外することになるでしょう:

@Test
public void testIsUserFullAge() throws Exception {
    //setup (having it here for brevity of the code sample)
    SimpleDateFormat format = new SimpleDateFormat("yyyy_MM_dd");
    Date D2000_01_01 = format.parse("2000_01_01");
    Date D1990_06_30 = format.parse("1990_06_30");
    User mockUserThatIsFullAge = mock(User.class);
    when(mockUserThatIsFullAge.getBirthday()).thenReturn(D1990_06_30);
    User mockUserThatIsNotFullAge = mock(User.class);
    when(mockUserThatIsNotFullAge.getBirthday()).thenReturn(D2000_01_01);

    //run
    asertTrue(MyUserUtil.isUserFullAge(mockUserThatIsFullAge));
    asertFalse(MyUserUtil.isUserFullAge(mockUserThatIsNotFullAge));
}

ここで重要なのは、コードがユーザーIDではなくUserオブジェクトで機能することです。したがって、ルックアップをテストする必要はありません。ルックアップも必死にテストしたい場合(たとえば、より広いスケールでのテスト)、それを統合テストと呼びます。ただし、関係のない変更が原因で頻繁に破損する場合でも、文句を言わないでください。テストが失敗する理由は、2つの異なる原因によるためです。ルックアップが失敗するか、実装が正しくありません。UNITテストを失敗させる理由の1つだけが必要です。たとえば、デバッグを開始するのではなく、テストが失敗したときに何がうまくいかなかったかをすぐに知ることができます。

そうそう、そのテストは2018年に失敗し始めます。実際には、もっと多くのコーナーケースをテストします。たとえば、明日18歳になるか、昨日18歳になった人などです)が、これは別のトピックです。

于 2012-08-16T07:50:54.253 に答える
0

私はLiferayサービスをモックするためにMockitoとPowerMockを使用しています。PowerMockを使用すると、のような静的メソッドをモックできますXXXLocalServiceUtil。Prakash Kからのリンクされた回答には、詳細な説明があります。カスタムプラグインポートレットのテスト:BeanLocatorExceptionおよびサービステストのトランザクションロールバック

于 2012-08-16T07:51:22.730 に答える