Como usar o método privado para testar usando o PowerMock?

Eu tenho uma class que gostaria de testar com um método público que chama privado. Eu gostaria de supor que o método privado funciona corretamente. Por exemplo, eu gostaria de algo como o doReturn....when... Eu descobri que existe uma possível solução usando o PowerMock , mas essa solução não funciona para mim. Como pode ser feito? Alguém tem esse problema?

Eu não vejo problema aqui. Com o seguinte código usando a API Mockito, consegui fazer exatamente isso:

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

E aqui está o teste da 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(); } } 

Uma solução genérica que funcionará com qualquer estrutura de teste ( se sua class for não final ) é criar manualmente sua própria simulação.

  1. Altere seu método privado para protegido.
  2. Na sua aula de teste, prolongue a class
  3. replace o método anteriormente privado para retornar a constante que você quiser

Isso não usa nenhum framework, então não é tão elegante, mas sempre funcionará: mesmo sem o PowerMock. Alternativamente, você pode usar o Mockito para fazer os passos 2 e 3 para você, se já tiver feito o passo 1.

Para zombar de um método privado diretamente, você precisará usar o PowerMock conforme mostrado na outra resposta .

Eu conheço uma maneira ny que você pode chamá-lo de function privada para testar em 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 alguma razão, a resposta de Brice não está funcionando para mim. Consegui manipular um pouco para que funcionasse. Pode ser porque eu tenho uma versão mais nova do PowerMock. Estou usando o 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; } } 

A class de teste é a seguinte:

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