Sto provando a prendere in giro per prendere in giro un metodo privato che sta effettuando una chiamata JNDI. Quando quel metodo viene chiamato da un test unitario, genera un'eccezione ^. Mi piacerebbe prendere in giro quel metodo per scopi di test. Ho usato lo sample code from another questions answer e, sebbene il test passi, sembra che il metodo sottostante venga ancora chiamato. Ho inserito uno System.err.println()
nel metodo doTheGamble()
e viene stampato sulla mia console.Metodo privato con Mocked con PowerMock, ma il metodo sottostante viene ancora chiamato
Interessante, se commento il primo assertThat
, il test ha esito positivo. ? :(
Allora, come faccio a mock di un metodo privato in modo che non ottiene chiamato?
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;
}
}
^comprensibilmente, dato che il mio lavoro non supporta JNDI, solo l'ambiente di produzione fa
% sto usando le ultime versioni di tutti i biblioteca, JUnit 4.10, Mockito 1.8.5, Hamcrest 1.1, Javassist 3.15.0, e PowerMock 1.4.10.
+1 per non danneggiare i bug. Molto premuroso di te;) – Guillaume
@Mike Hai idea del motivo 'doReturn (true) .when (spy," doTheGamble ", anyString(), anyInt());' funziona ma 'doReturn (true) .when (spia , method (CodeWithPrivateMethod.class, "doTheGamble", String.class, int.class)) .withArguments (anyString(), anyInt()); 'restituisce un 'IllegalArgumentException: tipo di argomento non corrispondente'? Quest'ultimo sembra più in linea con lo stile dell'esempio e almeno equivalente ma non funziona. – ArtB
Onestamente non posso, mi dispiace. Sono relativamente nuovo a Mockito/PowerMock stesso ... Non ho mai provato a scrivere codice in quello stile ('.withArguments (...)') prima. – Mike