mock method compatible and java junit mockito powermock

java - method - Método privado simulado con PowerMock, pero aún se llama al método subyacente



powermock maven (4)

ArtB,

¿Estás seguro de que tu código no funciona (o) me estoy perdiendo algo aquí? Acabo de reemplazar su expectativa de método con la siguiente, tal como lo sugirió Mike y funciona bien:

PowerMockito.doReturn(true).when(spy, method(CodeWithPrivateMethod.class, "doTheGamble", String.class, int.class)) .withArguments(anyString(), anyInt());

Nunca usé Powermockito pero usé mucho Mockito antes.

Estoy tratando de burlarme de burlarme de un método privado que está haciendo una llamada JNDI. Cuando ese método es llamado desde una prueba de unidad, lanza una excepción ^. Me gustaría burlarme de ese método con fines de prueba. Usé el código de ejemplo de otra pregunta , y mientras pasa la prueba, parece que aún se llama al método subyacente. System.err.println() un System.err.println() en el método doTheGamble() , y se imprime en mi consola.

Lo suficientemente interesante, si comento la primera assertThat , la prueba pasa. ? :(

Entonces, ¿cómo me burlo de un método privado para que no se llame?

import static org.hamcrest.core.Is.is; import static org.junit.Assert.assertThat; 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; import java.util.Random; 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; @RunWith(PowerMockRunner.class) @PrepareForTest(CodeWithPrivateMethod.class) public class PowerMock_Test { static boolean gambleCalled = false; @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); /* 1 */ assertThat( PowerMock_Test.gambleCalled, is(false) ); spy.meaningfulPublicApi(); /* 2 */ assertThat( PowerMock_Test.gambleCalled, is(false) ); } } 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(); System.err.println( "/n>>> GAMBLE CALLED <<</n" ); PowerMock_Test.gambleCalled = true; return gamble; } }

^ comprensiblemente, ya que mi espacio de trabajo no es compatible con JNDI, solo el entorno de producción lo hace

% Estoy usando las últimas versiones de toda la biblioteca, JUnit 4.10, Mockito 1.8.5, Hamcrest 1.1, Javassist 3.15.0 y PowerMock 1.4.10.


ArtB,

Solo pegando el código completo que funciona bien en mi IDE de Eclipse. Solo he cambiado la expectativa que dije en mi último post. Buena suerte.

import static org.hamcrest.core.Is.is; import static org.junit.Assert.assertThat; import static org.mockito.Matchers.anyInt; import static org.mockito.Matchers.anyString; import static org.powermock.api.support.membermodification.MemberMatcher.method; import java.util.Random; 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; @RunWith(PowerMockRunner.class) @PrepareForTest(CodeWithPrivateMethod.class) public class PowerMock_Test { static boolean gambleCalled = false; @Test(expected = RuntimeException.class) public void when_gambling_is_true_then_always_explode() throws Exception { CodeWithPrivateMethod spy = PowerMockito.spy(new CodeWithPrivateMethod()); // PowerMockito.doReturn(true).when(spy, "doTheGamble", anyString(), anyInt()); PowerMockito.doReturn(true).when(spy, method(CodeWithPrivateMethod.class, "doTheGamble", String.class, int.class)) .withArguments(anyString(), anyInt()); assertThat( PowerMock_Test.gambleCalled, is(false) ); spy.meaningfulPublicApi(); assertThat( PowerMock_Test.gambleCalled, is(false) ); } } 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(); System.err.println( "/n>>> GAMBLE CALLED <<</n" ); PowerMock_Test.gambleCalled = true; return gamble; } }


Del ejemplo del método privado PowerMock :

@RunWith(PowerMockRunner.class) // We prepare PartialMockClass for test because it''s 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"); }

Entonces, para aplicar esto a tu código, creo que podría convertirse en:

@RunWith(PowerMockRunner.class) @PrepareForTest(CodeWithPrivateMethod.class) public class PowerMock_Test { @Test(expected = RuntimeException.class) public void when_gambling_is_true_then_always_explode() throws Exception { CodeWithPrivateMethod spy = PowerMockito.spy(new CodeWithPrivateMethod()); PowerMockito.doReturn(true).when(spy, "doTheGamble", anyString(), anyInt()); /* 1 */ PowerMockito.verifyPrivate(spy, times(0)).invoke("doTheGamble", anyString(), anyInt()); spy.meaningfulPublicApi(); /* 2 */ PowerMockito.verifyPrivate(spy, times(2)).invoke("doTheGamble", anyString(), anyInt()); } }

Acabo de codificar eso en el editor aquí. En realidad, no se han ejecutado pruebas y no se han dañado errores en la elaboración de este código.


cuando usas un spy para construir un objeto simulado, es un objeto real con medio respaldo. Mi conjetura sería deshacerse del spy . Trabajar en puro objeto simulado.