PowerMock: как разблокировать метод?
У меня есть статический метод, который издевается с использованием PowerMock, чтобы выдать исключение. (Он удаляет файлы.) К сожалению, во время моего метода @After
(после каждого теста) мне нужно вызвать этот метод без mocks. Как я могу использовать метод?
Я не вижу эквивалента Mockito.reset()
. [Ссылка: mockito: как разблокировать метод?
Пример:
@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
Мне потребовалось некоторое время, чтобы разобраться, поэтому я отвечаю на свой вопрос.
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,
Класс тестирования
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";
}
}