2013-11-11 5 views
10

У меня есть статический метод, который издевается, используя PowerMock, чтобы выбросить исключение. (Он удаляет файлы.) К сожалению, во время моего метода @After (после каждого теста) мне нужно вызвать этот метод без макетов. Как я могу использовать метод?PowerMock: Как разблокировать метод?

Я не вижу эквивалента Mockito.reset(). [Ссылка: mockito : how to unmock a method?]

Пример:

@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(); 
    } 
} 

ответ

9

Это мне потребовалось некоторое время, чтобы выяснить, так что я отвечаю на мой собственный вопрос.

AFAIK, вам нужно «отменить» каждый макет. Mockito.reset() не будет работать с Class<?> ссылок. В конце методы тестирования, добавьте:

// 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

Единственный способом можно отменить насмешливые статический метод с PowerMock когда вы издеваться классом в начале теста, а затем отменить издеваются в конце теста. Не имеет значения, используете ли вы SPY или обычную насмешку.

Протестировано:

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

класса Test

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

действительно помогает мне. Еще один вопрос: зачем нам нужно называть 'assertThat (StaticTest.staticMethod()) isNull(); // отмена будет работать в следующем тесте, а не здесь. 'до отмены будет работать? –

+0

нам не обязательно делать утверждение isNull(). Я не помню, почему я сделал это в этом примере. Может быть, после doCallRealMethod(), если вы вызываете функцию, не вызывается издевательство или исходная реализация. Не помню. – maestr0

Смежные вопросы