LoginSignup
0
0

More than 3 years have passed since last update.

JMockitでテスト対象クラスから呼ばれるクラスの部分Mock方法メモ

Posted at

必要な状況

テスト対象クラスから呼ばれるクラスの一部のメソッドのみMock化したい場合

JMockit

1.46

結論

  1. ExpectationsにMock化したいインスタンスを渡して、Mock化したいメソッドのみExpectations内に定義する
  2. テスト対象クラスに(無理やり)設定する

テスト対象クラス

public class Sample {

    @Inject
    Hoge hoge;

    public String getHoge() {
        return hoge.getHoge() + hoge.getHogeUpper();
    }
}

テスト対象クラスからInjectしたHogeのメソッドを使用しています。
そのHogeについて部分Mockしたい場合の対処法となります。

テスト対象クラスから呼ばれるクラス

public class Hoge {

    public String getHoge() {
        return "hoge";
    }

    public String getHogeUpper() {
        return null;
    }
}

getHogeは実装完了しており、getHogeUpperはまだ未実装という状況としてください。

テスト失敗

public class SampleTest {

    @Tested
    Sample sample;

    @Injectable
    Hoge hoge;

    /**
     * テスト対象クラスから呼ばれるクラスの一部のメソッドのみMock化したいケース。
     * テストは失敗する。
     */
    @Test
    public void test() {

        new Expectations(hoge) {{
            hoge.getHogeUpper();
            result = "HOGE";
        }};

        String actual = sample.getHoge();
        assertThat(actual, is("hogeHOGE")); // actualはnullHOGEとなる
    }
}

テスト対象クラスはInjectを使用しているため、通常、JMockitの@Tested@Injectableでインスタンスを注入するようにかくと思いますが、それではテストは失敗します。
理由は、@InjectableでHogeのすべてのメソッドが空になるためです。

テスト成功

public class SampleTest2 {

    Sample sample = new Sample();

    /**
     * テスト対象クラスから呼ばれるクラスの一部のメソッドのみMock化したいケース。
     * テストは成功する。
     * @throws Exception
     * @throws NoSuchFieldException
     */
    @Test
    public void test() throws NoSuchFieldException, Exception {

        Hoge hoge = new Hoge();
        new Expectations(hoge) {
            {
                hoge.getHogeUpper();
                result = "HOGE";
            }
        };

        // Sampleのprivateフィールドに部分Mockしたhogeを設定
        Field field = sample.getClass().getDeclaredField("hoge");
        field.setAccessible(true);
        field.set(sample, hoge);

        String actual = sample.getHoge();
        assertThat(actual, is("hogeHOGE"));
    }
}

部分Mockの詳細は以下を参照してください。
https://jmockit-ja.nyamikan.net/tutorial/Mocking.html#partial
部分MockしたMockインスタンスを、リフレクションでテスト対象クラスに設定することでテストを成功させています。

最後に

JMockitの古いバージョンでは、MockUpで一部のみMock化し、getMockInstanceで取得したインスタンスをDeencapsulation.setFieldでテストクラスに設定していましたが、1.46ではどちらのメソッドも消えていました。。。
JMockitはAPIの削除が頻繁に行われているので、バージョンを新しくする際はご注意ください。
他に良い方法などあればぜひ教えて下さい。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0