Mocking behaviour resets after each test with PowerMock
13,339
The method PowerMockito.mockStatic(...)
invokes MockCreator.mock(...)
. This method regsiters a Runnable that will be executed after each test :
MockRepository.addAfterMethodRunner(new MockitoStateCleaner());
This runnable cleans the internal state of 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");
}
Related videos on Youtube
Author by
Kamil Seweryn
Updated on September 15, 2022Comments
-
Kamil Seweryn over 1 year
I'm writing unit tests using PowerMock, mocking behaviour of some util classes. Defining behaviour once for test class (by @BeforeClass annotation) causes:
- 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?
-
Kamil Seweryn over 11 yearsThanks for clearing that up. I understand that Mockito cleans the internal state of mocked objects after each test. I was just hoping not to invoke setUp() method once per test. Apparently PowerMockito.mock() acts the same.