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");
}
Share:
13,339

Related videos on Youtube

Kamil Seweryn
Author by

Kamil Seweryn

Updated on September 15, 2022

Comments

  • Kamil Seweryn
    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
    Kamil Seweryn over 11 years
    Thanks 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.