Pregunta

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

¿Fue útil?

Solución

No veo ningún problema aquí. Con el siguiente código usando la API Mockito, logré hacer exactamente 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 de 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();
    }
}

Otros consejos

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

  1. Cambie su método privado a protegido.
  2. En su clase de prueba extiende la clase
  3. anular el método previamente privado para devolver cualquier constante que desee

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

Para burlarse de un método privado directamente, deberá usar PowerMock como se muestra en el otra respuesta.

Sé de una manera que puede llamar su 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. Podría 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();
    }
}

Sin argumento:

ourObject = PowerMockito.spy(new OurClass());
when(ourObject , "ourPrivateMethodName").thenReturn("mocked result");

Con String argumento:

ourObject = PowerMockito.spy(new OurClass());
when(ourObject, method(OurClass.class, "ourPrivateMethodName", String.class))
                .withArguments(anyString()).thenReturn("mocked result");
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top