自クラスのstaticメソッドを呼び出すようなstaticメソッドのユニットテストを作成したが、テスト対象のメソッドが正常に実行できない問題が発生した。

TL;DR

CALLS_REAL_METHODSオプションを指定して、メソッドの実体を呼びだせるようにする。

MockedStatic<Hoge> hogeMockedStatic = mockStatic(Hoge.class, CALLS_REAL_METHODS)

概要

以下のようなstaticメソッドを2つ以上持つクラスがあって、publicなstaticメソッドからはもう片方のstaticメソッドが呼び出される。

このクラスについてユニットテストを作成したところ、テスト対象のメソッドの呼び出しがうまくいかなかった。

Hoge.javaclass Hoge {

    public static String static1() {
        return static2();
    }

    static String static2() {
        return "hoge";
    }
}

static2メソッドのユニットテストはhogeという文字列の返却をテストするだけなので簡単である。

しかし、static1メソッドは内部でstatic2メソッドを呼び出しているため、static2メソッドをモックするにはmockitoのMockedStaticを使う必要があった。

HogeTest.javaimport org.junit.jupiter.api.Test;
import org.mockito.MockedStatic;

import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.CALLS_REAL_METHODS;
import static org.mockito.Mockito.mockStatic;

class HogeTest {

    @Test
    void static1Test() {
        try (MockedStatic<Hoge> hogeMockedStatic = mockStatic(Hoge.class)) {
            hogeMockedStatic.when(() -> Hoge.static2()).thenReturn("piyo");
            assertThat(Hoge.static1()).isEqualTo("piyo"); // NG
        }
    }

    @Test
    void static2Test() {
        assertThat(Hoge.static2()).isEqualTo("hoge"); // OK
    }

}

上記のようなテストコードだと、Hoge.static1()の結果がnullとなるためテストは失敗する。

org.opentest4j.AssertionFailedError: 
Expecting:
 <null>
to be equal to:
 <"piyo">
but was not.
Expected :piyo
Actual   :null

nullが返却された原因は、モック化されたHogeクラスに対して、static1メソッドの振る舞いの定義がないため。

しかし、static1メソッドはテスト対象のメソッドなので、振る舞いを定義することはできない。

解決方法

mockitoのCALLS_REAL_METHODSオプションを利用する。

CALLS_REAL_METHODSオプションを指定することで、振る舞いが定義されていないメソッドは実体を呼び出せるようになる。

HogeTest.javaimport org.junit.jupiter.api.Test;
import org.mockito.MockedStatic;

import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.CALLS_REAL_METHODS;
import static org.mockito.Mockito.mockStatic;

class HogeTest {

    @Test
    void static1Test() {
        try (MockedStatic<Hoge> hogeMockedStatic
                     = mockStatic(Hoge.class, CALLS_REAL_METHODS)) {
            hogeMockedStatic.when(() -> Hoge.static2()).thenReturn("piyo");
            assertThat(Hoge.static1()).isEqualTo("piyo"); // OK
        }
    }

    @Test
    void static2Test() {
        assertThat(Hoge.static2()).isEqualTo("hoge"); // OK
    }

}