Mockitoのspyと例外

現象

spy使ってたら例外が出た。
例外のスタックトレースを見ると、when()が実行されるタイミングで実コードが実行されて、発生した例外が持ち出されてくるようだ。
mockを使った場合はこの現象は発生しない。

検証

ソースコード

package kurukuruz.test.mock;

public class Target {

    public String method1(String arg0) {
        throw new IllegalStateException("未実装!");
    }

    public static String smethod(String arg0) {
        throw new IllegalStateException("未実装!");
    }
}

テストコード

package kurukuruz.test.mock;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;

@RunWith(PowerMockRunner.class)
@PrepareForTest({Target.class})
public class TargetTest {

    @Test
    public void Mockito_mock() {
        System.out.println("---Mockito_mock---");
        Target t = Mockito.mock(Target.class);
        Mockito.when(t.method1("hoge")).thenReturn("mock");

        System.out.println(t.method1("hoge"));
        System.out.println(t.method1("foo"));
    }

    @Test
    public void Mockito_spy() {
        System.out.println("---Mockito_spy---");
        Target t = Mockito.spy(Target.class);
        Mockito.when(t.method1("hoge")).thenReturn("mock");

        System.out.println(t.method1("hoge"));
        System.out.println(t.method1("foo"));
    }

    @Test
    public void PowerMockito_mock() throws Exception {
        System.out.println("---PowerMockito_mock---");
        Target t = PowerMockito.mock(Target.class);
        PowerMockito.when(t, "method1", "hoge").thenReturn("mock");

        System.out.println(t.method1("hoge"));
        System.out.println(t.method1("foo"));
    }

    @Test
    public void PowerMockito_spy() throws Exception {
        System.out.println("---PowerMockito_spy---");
        Target t = PowerMockito.spy(new Target());
        PowerMockito.when(t, "method1", "hoge").thenReturn("mock");

        System.out.println(t.method1("hoge"));
        System.out.println(t.method1("foo"));
    }

    @Test
    public void PowerMockito_mockStatic() {
        System.out.println("---PowerMockito_mockStatic---");
        PowerMockito.mockStatic(Target.class);
        Mockito.when(Target.smethod("hoge")).thenReturn("mock");

        System.out.println(Target.smethod("hoge"));
        System.out.println(Target.smethod("foo"));
    }
}

実行結果

---PowerMockito_mock---
mock
null
---PowerMockito_mockStatic---
mock
null
---Mockito_spy---
---Mockito_mock---
mock
null
---PowerMockito_spy---

↓エラーが発生したケースのスタックトレース
f:id:kurukuruz:20180521114755j:plain