14

PowerMock を使用して単体テストを作成し、いくつかのユーティリティ クラスの動作をモックしています。( @BeforeClass アノテーションによって) テスト クラスに対して動作を 1 回定義すると、次のようになります。

  • モック値を返す最初のテスト呼び出し
  • 実際のメソッドの戻り値を返す 2 番目のテスト呼び出し

サンプルコード:

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

@RunWith(PowerMockRunner.class)
@PrepareForTest( {A.class, B.class})
public class TestMockedMethods {

private static B b;

@BeforeClass
public static void setUp() {
    PowerMockito.mockStatic(A.class);
    PowerMockito.when(A.getVal()).thenReturn("X");

    b = PowerMockito.mock(B.class);
    PowerMockito.when(b.getVal()).thenReturn("Y");
}

@Test
public void test1() { // PASS
    Assert.assertEquals("X", A.getVal());
    Assert.assertEquals("Y", b.getVal());
}

@Test
public void test2() { // FAIL
    Assert.assertEquals("X", A.getVal()); // actual="A"
    Assert.assertEquals("Y", b.getVal()); // actual="B"
}

}
class A {
  static String getVal() {
    return "A";
  }
}
class B {
  String getVal() {
    return "B";
  }
}

2番目のテストが失敗する理由はありますか?

4

1 に答える 1

21

メソッドは をPowerMockito.mockStatic(...)呼び出しますMockCreator.mock(...)このメソッドは、各テストの後に実行される Runnable を登録します。

MockRepository.addAfterMethodRunner(new MockitoStateCleaner());

このランナブルは Mockito の内部状態を消去します:

private static class MockitoStateCleaner implements Runnable {
    public void run() {
        clearMockProgress();
        clearConfiguration();
    }

    private void clearMockProgress() {
        clearThreadLocalIn(ThreadSafeMockingProgress.class);
    }

    private void clearConfiguration() {
        clearThreadLocalIn(GlobalConfiguration.class);
    }

    private void clearThreadLocalIn(Class<?> cls) {
        Whitebox.getInternalState(cls, ThreadLocal.class).set(null);
        final Class<?> clazz = ClassLoaderUtil.loadClass(cls, ClassLoader.getSystemClassLoader());
        Whitebox.getInternalState(clazz, ThreadLocal.class).set(null);
    }
}

したがって、各テストの前にセットアップを実行する必要があります。

@Before
public void setUp() {
    PowerMockito.mockStatic(A.class);
    PowerMockito.when(A.getVal()).thenReturn("X");

    b = PowerMockito.mock(B.class);
    PowerMockito.when(b.getVal()).thenReturn("Y");
}
于 2012-08-14T15:28:49.667 に答える