PowerMock: How to unmock a method?

前端 未结 2 1238
闹比i
闹比i 2021-02-19 02:27

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

相关标签:
2条回答
  • 2021-02-19 02:54

    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";
        }
    }
    
    0 讨论(0)
  • 2021-02-19 03:01

    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));
    
    0 讨论(0)
提交回复
热议问题