Domanda

Ho una classe che vorrei test con un metodo pubblico che chiama una privata. Mi piacerebbe pensare che metodo privato funziona correttamente. Ad esempio, mi piacerebbe qualcosa di simile doReturn....when.... Ho scoperto che ci sia possibile utilizzando PowerMock , ma questa soluzione non funziona per me. Come si può fare? Qualcuno ha ha questo problema?

È stato utile?

Soluzione

Non vedo un problema qui. Con il seguente codice utilizzando l'API Mockito, sono riuscito a fare proprio questo:

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

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

Altri suggerimenti

Una soluzione generica che funziona con qualsiasi framework di test ( se la classe è non-final) è quello di creare manualmente il proprio finto.

  1. Modificare il metodo privato a proteggere.
  2. Nella classe di test estendere la classe
  3. l'override del metodo precedentemente privato a restituire tutto quello che vuoi costante

Questa non utilizzare alcun quadro quindi non è elegante, ma funziona sempre: anche senza PowerMock. In alternativa, è possibile utilizzare Mockito fare passi # 2 e # 3 per te, se hai passo done # 1 già.

per deridere un metodo privato direttamente, avrete bisogno di usare PowerMock come mostrato nella altra risposta .

So che un modo ny cui è possibile chiamare la funzione privato a prova 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);
    }

Per qualche ragione la risposta di Brice non funziona per me. Sono stato in grado di manipolare un po 'per farlo funzionare. Potrebbe essere solo perché ho una versione più recente di PowerMock. Sto utilizzando 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;
    }
}

L'aspetto classe di test come segue:

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

Con alcun argomento:

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

Con argomento String:

ourObject = PowerMockito.spy(new OurClass());
when(ourObject, method(OurClass.class, "ourPrivateMethodName", String.class))
                .withArguments(anyString()).thenReturn("mocked result");
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top