Engineering Note

プログラミングなどの技術的なメモ

privateメソッド内で実行するprivateフィールドのメソッドをモック化

Mockitoを利用したテスト時に、privateメソッド内で@Autowierdされたprivateフィールドが持つメソッドをモック化した場合のメモになります。

 

 

事前準備

今回のテスト用に以下のコードを作成します。

 

  • Sampleクラス:@Autowierdしたprivateフィールド(Personクラス)を持ち、privateメソッド(foo())でPerson.getName()の結果を返す
  • Personクラス:privateフィールド及びそのゲッターを持つ

 

 // Person.java

@Getter
public class Person {
    private String name = "foo";
}

 

// Sample.java

public class Sample {
    @Autowired
    private Person person;

    private String foo() {
        String name = this.person.getName();
        return name;
    }
}

 

テストコードの作成

以下が作成したテストコードとなります。

 

 // SampleTest.java


public class SampleTest {

    private Sample sample = new Sample();
    private Person person;

    @Before
    public void setup() {
        MockitoAnnotations.openMocks(this);
        this.initPerson();
    }

    @After
    public void tearDown() throws Exception {
    }
    
    @Test
    public void testFoo() {
        when(this.person.getName()).thenReturn("bar");

        String result = null;
        try {
            result = Whitebox.invokeMethod(this.sample, "foo");
        } catch (Exception e) {
            e.printStackTrace();
            fail();
        }
        MatcherAssert.assertThat(result, CoreMatchers.is("bar"));
    }

    private void initPerson() {
        Whitebox.setInternalState(this.sample, "person", Mockito.mock(Person.class));

        Field field = null;
        try {
            field = Sample.class.getDeclaredField("person");
            field.setAccessible(true);
            this.person = (Person) field.get(this.sample);
        } catch (Exception e) {
            e.printStackTrace();
            fail();
        }
    }
}

 

今回はPowermockのWhiteBoxというユーティリティクラスを使用し、インスタンス化したテスト対象クラスのprivateフィールドをモッククラスとして上書きする方法を取りました。

そのフィールドインスタンスをリフレクションを利用しアクセスすることで、カプセル化された箇所のテストも容易にできます。

 

参考書籍

Java本格入門 ~モダンスタイルによる基礎からオブジェクト指向・実用ライブラリまで