Mocking behaviour resets after each test with PowerMock

匿名 (未验证) 提交于 2019-12-03 00:56:02

问题:

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?

回答1:

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"); } 


易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!