java - compatible - powermock maven
¿Cómo burlarse del método privado para probar usando PowerMock? (4)
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);
}
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();
}
}
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();
}
}
Una solución genérica que funcionará con cualquier marco de prueba ( si su clase no es final
) es crear manualmente su propio simulacro.
- Cambie su método privado a protegido.
- En tu clase de prueba, extiende la clase
- 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 .