Java 每次使用PowerMock测试后,模拟行为都会重置
我正在使用PowerMock编写单元测试,模拟一些util类的行为。为测试类定义一次行为(通过@BeforeClass注释)会导致:Java 每次使用PowerMock测试后,模拟行为都会重置,java,unit-testing,mocking,powermock,Java,Unit Testing,Mocking,Powermock,我正在使用PowerMock编写单元测试,模拟一些util类的行为。为测试类定义一次行为(通过@BeforeClass注释)会导致: 返回模拟值的第一次测试调用 返回实际方法返回值的第二次测试调用 示例代码: import org.junit.Assert; import org.junit.BeforeClass; import org.junit.Test; import org.junit.runner.RunWith; import org.powermock.api.mockito
- 返回模拟值的第一次测试调用
- 返回实际方法返回值的第二次测试调用
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";
}
}
知道第二次测试失败的原因吗?方法
PowerMockito.mockStatic(…)
调用MockCreator.mock(…)
。此方法注册一个Runnable,该Runnable将在每次测试后执行:
MockRepository.addAfterMethodRunner(new MockitoStateCleaner());
此runnable清除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);
}
}
谢谢你澄清这一点。我知道Mockito在每次测试后都会清理模拟对象的内部状态。我只是希望每次测试不要调用setUp()方法一次。显然,PowerMockito.mock()的作用是相同的。
@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");
}