¿Cómo burlarse del método privado para probar usando PowerMock?

Tengo una clase que me gustaría probar con un método público que llama privado. Me gustaría asumir que el método privado funciona correctamente. Por ejemplo, me gustaría algo como doReturn....when... Descubrí que hay una solución posible usando PowerMock , pero esta solución no funciona para mí. ¿Cómo se puede hacer? ¿Alguien tiene este problema?

No veo un problema aquí. Con el siguiente código usando la API de Mockito, logré hacer eso:

 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; } } 

Y aquí está la prueba 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(); } } 

Una solución genérica que funcionará con cualquier marco de prueba ( si su clase no es final ) es crear manualmente su propio simulacro.

  1. Cambie su método privado a protegido.
  2. En tu clase de prueba, extiende la clase
  3. anula el método previamente privado para devolver la constante que quieras

Esto no utiliza ningún marco, por lo que no es tan elegante, pero siempre funcionará: incluso sin PowerMock. Alternativamente, puede usar Mockito para realizar los pasos 2 y 3, si ya ha realizado el paso 1.

Para simular un método privado directamente, deberá usar PowerMock como se muestra en la otra respuesta .

Conozco una manera ny que puede llamarle función privada para probar en 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); } 

Por alguna razón, la respuesta de Brice no funciona para mí. Pude manipularlo un poco para que funcione. Puede ser porque tengo una versión más nueva de PowerMock. Estoy usando 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; } } 

La clase de prueba se ve de la siguiente manera:

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