クリエイター:メタボ兔

ウェブやアプリの開発者で利用する色な技術やサーバーや開発環境の設定について共有する場

EasyMockでcmp、capture

概要

EasyMockを利用してテストケースを作成する際に以下の内容で対応方法を調べていました。

  • mainのソースのクラスのequalsをオーバーライドする等、テストの為に修正はしたくない
  • メソッド内部の変数をテスト内容に入れないので、expectで確認するメソッドのパラメターを判定したい

例のソース

Map<String, String> expectMap = new HashMap<String, String>();
...
sampleClass.test(eq(stringA), eq(intB), eq(mapC), eq(booleanD));

確認したい内容

  • mapCのキー&値が一致
  • mapCの特定のキーについては除外

eqのような判定をカスタマイズ

eqと比較内容をカスタマイズすれば「確認したい内容」のみ定義できるかと思いました調べたところ以下のような内容がありました。

stackoverflow.com

こんな感じで作ってみました。expectMapにあるキーを基準で比較するのを想定しました。

   // 比較内容を定義
    private class MapComparator implements Comparator<Map<String, String>> {
        @Override
        public int compare(Map<String, String> expected, Map<String, String> actual) {
            for (String key : expected.keySet()) {
                if (!actual.containsKey(key)) return -1;
                if (!StringUtils.equals(expected.get(key), actual.get(key))) return 1;
            }
            return 0;
        }       
    }
    
...

    // 使用例
    Map<String, String> expectMap = new HashMap<String, String>();
    expectMap.put("key1", "value1");
    expectMap.put("key2", "value2");

    MapComparator mapComparator = new MapComparator();
    
    sampleClass.test(eq(stringA), eq(intB), EasyMock.cmp(expectMap, mapComparator, LogicalOperator.EQUAL), eq(booleanD));
    EasyMock.expectLastCall();
...

結果

結果としてダメでした。MapComparator#compareがテストメソッドのパラメーター分繰り返して呼ばれて、actualにtestメソッドの第一パラメーターから第四パラメーターが順番で入ってくることになります。

それでcast exceptionが発生されます。これを使えるのはパラメーターが一つの場合のみかと思います。

capture

cmpでパラメーターが複数の時の対応が出来ないことで調査を続けるとEasyMock.captureというものがありました。テストメソッドが呼ばれる時の値を指定した変数に格納(?)してくれるので後で値を比較が可能になります。

www.programcreek.com

...
    // sampleClass.testが実行する時、第3番目のパラメターがcaptureFeatureSetTagへ格納される。
    Capture<Map<String, String>> actualCapture = new Capture<Map<String,String>>();
    sampleClass.test(eq(stringA), eq(intB), EasyMock.capture(actualCapture), eq(booleanD));
    EasyMock.expectLastCall();

    // テスト対象のメソッドを実行
    replayAll();
    testClass.excute(parameter);
    verifyAll();
        
    // 使用例
    Map<String, String> expectMap = new HashMap<String, String>();
    expectMap.put("key1", "value1");
    expectMap.put("key2", "value2");

    // captureFeatureSetTagと比較("key3"を除外)
    Map<String, String> actualMap = actualCapture.getValue();
    actualMap.remove("key3");
    assertEquals(expectMap, actualMap);
...

結論

今回の対応ではEasyMock.captureを利用して対応ができましたが、個人的にはcmpもやってみたいなと思いました。