PowerMock: How to unmock a method?

匿名 (未验证) 提交于 2019-12-03 08:36:05

问题:

I have a static method that is mocked using PowerMock to throw an exception. (It deletes files.) Unfortunately, during my @After (after-each-test) method, I need to call this method without the mocks. How can I umock a method?

I don't see an equivalent to Mockito.reset(). [ Ref: mockito : how to unmock a method? ]

Example:

@RunWith(PowerMockRunner.class) @PrepareForTest(PathUtils.class)  // Important: This class has a static method we want to mock. public class CleaningServiceImplTest2 extends TestBase {      public static final File testDirPath = new File(CleaningServiceImplTest2.class.getSimpleName());      @BeforeClass     public static void beforeAllTests() throws PathException {         recursiveDeleteDirectory(testDirPath);     }      @AfterClass     public static void afterAllTests() throws PathException {         recursiveDeleteDirectory(testDirPath);     }      private File randomParentDirPath;     private CleaningServiceImpl classUnderTest;      @Before     public void beforeEachTest() {         randomParentDirPath = new File(testDirPath, UUID.randomUUID().toString()).getAbsoluteFile();         classUnderTest = new CleaningServiceImpl(randomParentDirPath);     }      @After     public void afterEachTest() throws PathException {         recursiveDeleteDirectory(randomParentDirPath);     }      public static void recursiveDeleteDirectory(File dirPath) throws PathException {         // calls PathUtils.removeFile(...)     }      @Test     public void run_FailWhenCannotRemoveFile() throws IOException {         // We only want to mock one method.  Use spy() and not mockStatic().         PowerMockito.spy(PathUtils.class);          // These two statements are tightly bound.         PowerMockito.doThrow(new PathException(PathException.PathExceptionReason.UNKNOWN, randomParentDirPath, null, "message"))             .when(PathUtils.class);         PathUtils.removeFile(Mockito.any(File.class));          classUnderTest.run();     } } 

回答1:

This took me a while to figure out, so I am answering my own question.

AFAIK, you need to "undo" each mock. Mockito.reset() will not work with Class<?> references. At the end of the test method, add:

// Undo the mock above because we need to call PathUtils.removeFile() within @After. PowerMockito.doCallRealMethod().when(PathUtils.class); PathUtils.removeFile(Mockito.any(File.class)); 


回答2:

The only way you can undo mocking of a static method with PowerMock is when you mock a class at the beginning of a test and then undo the mock at the end of a test. It doesn't matter if you use SPY or a regular mocking.

Tested with:

"org.powermock" % "powermock" % "1.5" % Test, "org.powermock" % "powermock-api-mockito" % "1.6.1" % Test, 

Test class

package mytests;  import org.junit.After; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mockito; import org.powermock.api.mockito.PowerMockito; import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.modules.junit4.PowerMockRunner;  import static org.fest.assertions.Assertions.assertThat;   @RunWith(PowerMockRunner.class) @PrepareForTest({StaticTest.class}) public class TestTest {      @Before     public void checkIfOriginalMethodGetsCalled() {  //        PowerMockito.mockStatic(StaticTest.class); if you do this in @Before you are not going to be able to undo it         assertThat(StaticTest.staticMethod()).isEqualTo("ORIGINAL VALUE");         assertThat(StaticTest.otherStaticMethod()).isEqualTo("SPY TEST ORIGINAL");     }      @Test     public void test1() {         assertThat(StaticTest.staticMethod()).isEqualTo("ORIGINAL VALUE");     }      @Test     public void test3_mocking() {         mock(); // mock or spy static methods in a test, not in @Before           Mockito.when(StaticTest.staticMethod()).thenReturn("MOCKED VALUE");         assertThat(StaticTest.staticMethod()).isEqualTo("MOCKED VALUE");         assertThat(StaticTest.otherStaticMethod()).isEqualTo("SPY TEST ORIGINAL");          undoMock(); // undo the mock at the end of each test, not in @After     }      private void mock() { //        PowerMockito.mockStatic(StaticTest.class); both, spy and mockStatic work ok         PowerMockito.spy(StaticTest.class);     }      private void undoMock() {         PowerMockito.doCallRealMethod().when(StaticTest.class);         assertThat(StaticTest.staticMethod()).isNull(); // the undo is going to work in the next test, not here yet.      }      @Test     public void test2() {         assertThat(StaticTest.staticMethod()).isEqualTo("ORIGINAL VALUE");     }      @After     public void checkIfOriginalMethodGetsCalled_AfterMockUndo() {          // undoMock(); in @After  doesn't work with static methods         assertThat(StaticTest.staticMethod()).isEqualTo("ORIGINAL VALUE");         assertThat(StaticTest.otherStaticMethod()).isEqualTo("SPY TEST ORIGINAL");     } }  class StaticTest {     public static String staticMethod() {         return "ORIGINAL VALUE";     }      public static String otherStaticMethod() {         return "SPY TEST ORIGINAL";     } } 


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