Question

J'ai une classe que je voudrais tester une méthode publique qui appelle un privé. Je voudrais penser que la méthode fonctionne correctement privée. Par exemple, je voudrais quelque chose comme doReturn....when.... Je trouve qu'il ya solution possible à l'aide PowerMock, mais cette solution ne fonctionne pas pour moi. Comment ça peut se faire? Est-ce que quelqu'un a ce problème?

Était-ce utile?

La solution

Je ne vois pas un problème ici. Avec le code suivant à l'aide de l'API Mockito, j'ai réussi à le faire que:

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

Et voici le test 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();
    }
}

Autres conseils

Une solution générique qui fonctionnera avec un framework de test ( si votre classe est non-final) est de créer manuellement votre propre maquette.

  1. Changer votre méthode privée protégée.
  2. Dans votre classe de test étendre la classe
  3. remplacer la méthode précédemment privée pour revenir tout constant que vous voulez

Cela ne pas utiliser tout cadre donc son pas aussi élégant mais il travaillerai toujours: même sans PowerMock. Vous pouvez également utiliser Mockito pour faire les étapes # 2 et # 3 pour vous, si vous avez pas fini # 1 déjà.

Pour se moquer d'une méthode privée directement, vous aurez besoin d'utiliser PowerMock comme indiqué dans le autre réponse .

Je sais que d'une manière ny que vous pouvez vous appeler la fonction privée à tester dans 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);
    }

Pour une raison quelconque la réponse de Brice ne fonctionne pas pour moi. J'ai pu manipuler un peu pour le faire fonctionner. Il est peut-être juste parce que j'ai une version plus récente de PowerMock. J'utilise 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;
    }
}

Les regards de la classe de test comme suit:

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

Sans argument:

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

Avec argument String:

ourObject = PowerMockito.spy(new OurClass());
when(ourObject, method(OurClass.class, "ourPrivateMethodName", String.class))
                .withArguments(anyString()).thenReturn("mocked result");
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top