Можно ли использовать частичное издевательство для частных статических методов в PowerMock?
Из примеров на домашней странице PowerMock, я вижу следующий пример для частичного издевательства частного метода с Mockito:
@RunWith(PowerMockRunner.class)
// We prepare PartialMockClass for test because it final or we need to mock private or static methods
@PrepareForTest(PartialMockClass.class)
public class YourTestCase {
@Test
public void privatePartialMockingWithPowerMock() {
PartialMockClass classUnderTest = PowerMockito.spy(new PartialMockClass());
// use PowerMockito to set up your expectation
PowerMockito.doReturn(value).when(classUnderTest, "methodToMock", "parameter1");
// execute your test
classUnderTest.execute();
// Use PowerMockito.verify() to verify result
PowerMockito.verifyPrivate(classUnderTest, times(2)).invoke("methodToMock", "parameter1");
}
Однако этот подход не работает, когда частный метод, который мы хотим высмеять, является статическим. Я хочу создать частичный макет этого класса, с помощью метода readFile:
package org.rich.powermockexample;
import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.List;
import static com.google.common.io.Files.readLines;
public class DataProvider {
public static List<String> getData() {
List<String> data = null;
try {
data = readFile();
} catch (IOException e) {
e.printStackTrace();
}
return data;
}
private static List<String> readFile() throws IOException {
File file = new File("/some/path/to/file");
List<String> lines = readLines(file, Charset.forName("utf-8"));
return lines;
}
}
Пожалуйста, позвольте мне сообщить, как это можно достичь?
Ответы
Ответ 1
После нескольких дополнительных исследований кажется, что PowerMockito.spy() и PowerMockito.doReturn() здесь необходимы:
package com.richashworth.powermockexample;
import org.junit.Before;
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;
import java.util.ArrayList;
import java.util.List;
import static org.junit.Assert.assertEquals;
@RunWith(PowerMockRunner.class)
@PrepareForTest({DataProvider.class})
public class ResultsWriterTest {
private static List<String> mockData = new ArrayList<String>();
private ResultsWriter resultsWriter;
@BeforeClass
public static void setUpOnce() {
final String firstLine = "Line 1";
final String secondLine = "Line 2";
mockData.add(firstLine);
mockData.add(secondLine);
}
@Before
public void setUp() {
resultsWriter = new ResultsWriter();
}
@Test
public void testGetDataAsString() throws Exception {
PowerMockito.spy(DataProvider.class);
PowerMockito.doReturn(mockData).when(DataProvider.class, "readFile");
final String expectedData = "Line 1\nLine 2\n";
final String returnedString = resultsWriter.getDataAsString();
assertEquals(expectedData, returnedString);
}
}
Ответ 2
Класс тестирования:
@RunWith(PowerMockRunner.class)
@PrepareForTest(DataProvider.class)
public class DataProviderTest {
@Test
public void testGetDataWithMockedRead() throws Exception {
mockStaticPartial(DataProvider.class, "readFile");
Method[] methods = MemberMatcher.methods(DataProvider.class, "readFile");
expectPrivate(DataProvider.class, methods[0]).andReturn(Arrays.asList("ohai", "kthxbye"));
replay(DataProvider.class);
List<String> theData = DataProvider.getData();
assertEquals("ohai", theData.get(0));
assertEquals("kthxbye", theData.get(1));
}
}
Проверяемый класс (в основном ваш):
public class DataProvider {
public static List<String> getData() {
try {
return readFile();
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
private static List<String> readFile() throws IOException {
File file = new File("/some/path/to/file");
return readLines(file, Charset.forName("utf-8"));
}
}
Ответ 3
В общем, используйте только статические методы издевательства над классами, которые находятся вне вашего контроля (например, java.io.File
). Поскольку DataProvider
и readFile
являются вашими собственными, refactor DataProvider
в правильный класс (т.е. Делают его методы нестатическими), вытащите readFile
в вспомогательный объект и затем издевайтесь над этим. См. Этот ответ fooobar.com/info/235623/....