java 每次使用 PowerMock 进行测试后,模拟行为都会重置
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/11955270/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Mocking behaviour resets after each test with PowerMock
提问by Kamil Seweryn
I'm writing unit tests using PowerMock, mocking behaviour of some util classes. Defining behaviour once for test class (by @BeforeClass annotation) causes:
我正在使用 PowerMock 编写单元测试,模拟一些 util 类的行为。为测试类定义一次行为(通过@BeforeClass 注释)会导致:
- first test invocation to return mocked value
- second test invocation to return real method return value
- 第一次测试调用返回模拟值
- 返回真实方法返回值的第二次测试调用
Sample code:
示例代码:
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";
}
}
Any ideas why second test is failing?
任何想法为什么第二次测试失败?
回答by gontard
The method PowerMockito.mockStatic(...)
invokes MockCreator.mock(...)
. This method regsiters a Runnable that will be executed after each test:
该方法PowerMockito.mockStatic(...)
调用MockCreator.mock(...)
. 此方法注册一个 Runnable,它将在每次测试后执行:
MockRepository.addAfterMethodRunner(new MockitoStateCleaner());
This runnable cleans the internal state of Mockito:
这个 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);
}
}
So you should execute your setUp before each test.
所以你应该在每次测试之前执行你的设置。
@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");
}