Как издеваться над частным методом тестирования с помощью PowerMock?
У меня есть класс, который я хотел бы проверить с помощью публичного метода, который вызывает private one. Я хотел бы предположить, что частный метод работает правильно. Например, я хотел бы что-то вроде doReturn....when...
. Я обнаружил, что есть возможное решение с помощью PowerMock, но это решение не работает для меня.
Как это можно сделать? У кого-нибудь была эта проблема?
4 ответа:
Я не вижу здесь проблемы. С помощью следующего кода, используя API Mockito, мне удалось сделать именно это:
public class CodeWithPrivateMethod { public void meaningfulPublicApi() { if (doTheGamble("Whatever", 1 << 3)) { throw new RuntimeException("boom"); } } private boolean doTheGamble(String whatever, int binary) { Random random = new Random(System.nanoTime()); boolean gamble = random.nextBoolean(); return gamble; } }
и вот тест JUnit :
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 static org.mockito.Matchers.anyInt; import static org.mockito.Matchers.anyString; import static org.powermock.api.mockito.PowerMockito.when; import static org.powermock.api.support.membermodification.MemberMatcher.method; @RunWith(PowerMockRunner.class) @PrepareForTest(CodeWithPrivateMethod.class) public class CodeWithPrivateMethodTest { @Test(expected = RuntimeException.class) public void when_gambling_is_true_then_always_explode() throws Exception { CodeWithPrivateMethod spy = PowerMockito.spy(new CodeWithPrivateMethod()); when(spy, method(CodeWithPrivateMethod.class, "doTheGamble", String.class, int.class)) .withArguments(anyString(), anyInt()) .thenReturn(true); spy.meaningfulPublicApi(); } }
универсальное решение, которое будет работать с любой системой тестирования (Если ваш класс не
final
), чтобы вручную создать свой собственный макет.
- измените свой частный метод на защищенный.
- в вашем тестовом классе расширьте класс
- переопределите ранее закрытый метод, чтобы вернуть любую константу, которую вы хотите
Это не использует никаких рамок, так что его не так элегантно, но он всегда будет работать: даже без PowerMock. Кроме того, вы можете использовать Mockito, чтобы сделать шаги #2 & #3 для вас, если вы уже сделали шаг #1.
чтобы издеваться над частным методом напрямую, вам нужно будет использовать PowerMock, как показано в другого ответа.
Я знаю способ ny, который вы можете назвать частной функцией для тестирования в mockito
@Test public void commandEndHandlerTest() throws Exception { Method retryClientDetail_privateMethod =yourclass.class.getDeclaredMethod("Your_function_name",null); retryClientDetail_privateMethod.setAccessible(true); retryClientDetail_privateMethod.invoke(yourclass.class, null); }
по какой-то причине ответ Брайса не работает для меня. Я смог немного манипулировать им, чтобы заставить его работать. Это может быть просто потому, что у меня более новая версия PowerMock. Я использую 1.6.5.
import java.util.Random; public class CodeWithPrivateMethod { public void meaningfulPublicApi() { if (doTheGamble("Whatever", 1 << 3)) { throw new RuntimeException("boom"); } } private boolean doTheGamble(String whatever, int binary) { Random random = new Random(System.nanoTime()); boolean gamble = random.nextBoolean(); return gamble; } }
тестовый класс выглядит следующим образом:
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 static org.mockito.Matchers.anyInt; import static org.mockito.Matchers.anyString; import static org.powermock.api.mockito.PowerMockito.doReturn; @RunWith(PowerMockRunner.class) @PrepareForTest(CodeWithPrivateMethod.class) public class CodeWithPrivateMethodTest { private CodeWithPrivateMethod classToTest; @Test(expected = RuntimeException.class) public void when_gambling_is_true_then_always_explode() throws Exception { classToTest = PowerMockito.spy(classToTest); doReturn(true).when(classToTest, "doTheGamble", anyString(), anyInt()); classToTest.meaningfulPublicApi(); } }