it-swarm-id.com

Bagaimana cara mengejek metode pribadi untuk pengujian menggunakan PowerMock?

Saya memiliki kelas yang ingin saya uji dengan metode publik yang memanggil kelas privat. Saya ingin mengasumsikan bahwa metode pribadi berfungsi dengan benar. Sebagai contoh, saya suka sesuatu seperti doReturn....when.... Saya menemukan bahwa ada kemungkinan solusi menggunakan PowerMock , tetapi solusi ini tidak berfungsi untuk saya. Bagaimana itu bisa dilakukan? Apakah ada yang punya masalah ini?

59
Julie Langstrump

Saya tidak melihat masalah di sini. Dengan kode berikut menggunakan Mockito API, saya berhasil melakukan hal itu:

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

Dan inilah tes 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();
    }
}
92
Brice

Solusi umum yang akan bekerja dengan kerangka pengujian apa pun ( jika kelas Anda adalah non -final) adalah secara manual membuat tiruan Anda sendiri.

  1. Ubah metode pribadi Anda menjadi terlindungi.
  2. Di kelas tes Anda memperpanjang kelas
  3. ganti metode yang sebelumnya pribadi untuk mengembalikan konstanta apa pun yang Anda inginkan

Ini tidak menggunakan kerangka kerja apa pun sehingga tidak seelegan itu tetapi akan selalu berfungsi: bahkan tanpa PowerMock. Atau, Anda dapat menggunakan Mockito untuk melakukan langkah # 2 & # 3 untuk Anda, jika Anda sudah melakukan langkah # 1.

Untuk mengolok-olok metode pribadi secara langsung, Anda harus menggunakan PowerMock seperti yang ditunjukkan pada jawaban lain .

21
Tobogganski

Entah mengapa jawaban Brice tidak bekerja untukku. Saya bisa memanipulasi sedikit untuk membuatnya berfungsi. Mungkin saja karena saya memiliki versi PowerMock yang lebih baru. Saya menggunakan 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;
    }
}

Kelas tes terlihat sebagai berikut:

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

saya tahu cara ny yang Anda dapat memanggil Anda fungsi pribadi untuk menguji di 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);
    }
1
Arun Yadav