Frage

Ich habe eine Klasse, die ich mit einer öffentlichen Methode testen möchte, die privat nennt. Ich möchte annehmen, dass die private Methode richtig funktioniert. Zum Beispiel hätte ich so etwas wie doReturn....when.... Ich fand, dass es gibt mögliche Lösung mit PowerMock, Aber diese Lösung funktioniert bei mir nicht. Wie kann es gemacht werden? Hatte jemand dieses Problem?

War es hilfreich?

Lösung

Ich sehe hier kein Problem. Mit dem folgenden Code mit der Mockito -API habe ich genau das geschafft:

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

Und hier ist der Junit -Test:

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

Andere Tipps

Eine generische Lösung, die mit jedem Test -Framework funktioniert (wenn Ihre Klasse ist nichtfinal) ist manuell ein eigenes Schein zu kreieren.

  1. Ändern Sie Ihre private Methode in Schutz.
  2. In Ihrer Testklasse erweitern Sie die Klasse
  3. Überschreiben Sie die zuvor private Methode, um die gewünschte Konstante zurückzugeben

Dies verwendet kein Framework, daher ist es nicht so elegant, aber es wird immer funktionieren: auch ohne PowerMock. Alternativ können Sie Mockito verwenden, um die Schritte Nr. 2 & #3 für Sie auszuführen, wenn Sie bereits Schritt 1 durchgeführt haben.

Um eine private Methode direkt zu verspotten, müssen Sie PowerMock wie in der gezeigt verwenden Andere Antwort.

Ich kenne einen Weg, den Sie in Mockito als private Funktion nennen können

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

Aus irgendeinem Grund funktioniert Brices Antwort nicht für mich. Ich konnte es ein wenig manipulieren, um es zum Laufen zu bringen. Es könnte nur daran liegen, dass ich eine neuere Version von PowerMock habe. Ich benutze 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;
    }
}

Die Testklasse sieht wie folgt aus:

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

Ohne Argument:

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

Mit String Streit:

ourObject = PowerMockito.spy(new OurClass());
when(ourObject, method(OurClass.class, "ourPrivateMethodName", String.class))
                .withArguments(anyString()).thenReturn("mocked result");
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top