Menggunakan PowerMockito.whenNew () tidak diejek dan metode asli dipanggil

103

Saya memiliki kode seperti ini di bawah ini:

Class A {
  public boolean myMethod(someargs) {
    MyQueryClass query = new MyQueryClass();
    Long id = query.getNextId();
    // some more code
  }
}
Class MyQueryClass     {
  ....
  public Long getNextId() {
    //lot of DB code, execute some DB query
    return id;
  }
}

Sekarang saya sedang menulis tes untuk A.myMethod(someargs). Saya ingin melewatkan metode sebenarnya query.getNextId()dan sebagai gantinya mengembalikan nilai rintisan. Pada dasarnya, saya ingin mengejek MyQueryClass.

Jadi dalam kasus uji saya, saya telah menggunakan:

MyQueryClass query = PowerMockito.mock(MyQueryClass.class);
PowerMockito.whenNew(MyQueryClass.class).withNoArguments().thenReturn(query);
when(query.getNextId()).thenReturn(1000000L);

boolean b = A.getInstance().myMethod(args);

//asserts

Saya menggunakan @RunWith(PowerMockRunner.class)dan @PrepareForTest({MyQueryClass.class})di awal kelas pengujian saya.

Tapi ketika saya debug tes, masih memanggil metode nyata getNextId()dari MyQueryClasskelas.

Apa yang kulewatkan di sini? Adakah yang bisa membantu karena saya baru mengenal Mockito dan PowerMockito.

pengguna3942446
sumber

Jawaban:

226

Anda perlu meletakkan kelas tempat konstruktor dipanggil ke dalam @PrepareForTestanotasi, bukan kelas yang sedang dibangun - lihat Konstruksi tiruan objek baru .

Dalam kasus Anda:

@PrepareForTest(MyQueryClass.class)

@PrepareForTest(A.class)

Lebih umum:

@PrepareForTest(NewInstanceClass.class)

@PrepareForTest(ClassThatCreatesTheNewInstance.class)

TrueDub
sumber
1
Terima kasih banyak. Ini berfungsi sekarang setelah menyertakan kelas saat ini Eg A di @PrepareForTest.
pengguna3942446
2
Saya menghabiskan waktu untuk ini juga. Terima kasih @TrueDub. Karena referensinya sudah ketinggalan zaman. Saya baru saja memperbaruinya. github.com/jayway/powermock/wiki/MockConstructor Bunyinya: Gunakan anotasi @PrepareForTest (ClassThatCreatesTheNewInstance.class) di tingkat kelas kasus uji.
Victor Choy
4
Saya memiliki masalah yang sama, tetapi solusi ini tidak berhasil untuk saya
dexter
3
Solusi ini tidak akan berfungsi jika Anda menggunakan eclemma untuk cakupan kode. Menambahkan kelas yang diuji ke @PrepareForTest akan menghasilkan cakupan 0% untuk kelas itu
ACV
2
Solusinya akan bekerja - tes dijalankan dengan benar. Jelas eclemma tidak dilengkapi untuk menangani PowerMockito. Cakupan kode bukan bagian dari pertanyaan ini.
TrueDub
3

Seperti yang disebutkan @TrueDub dalam balasannya yang diterima, Anda perlu menambahkan kelas tempat konstruktor dipanggil ke @PrepareForTest.

Namun, jika Anda melakukan ini, cakupan untuk kelas itu seperti yang dilaporkan oleh eclemma dan Sonar akan menjadi nol untuk kelas itu

Wiki Powermockito

Kami akan mengganti Javassist dengan ByteBuddy (# 727) dan itu akan membantu menyelesaikan masalah lama ini. Tapi saat ini TIDAK ADA CARA MENGGUNAKAN PowerMock dengan instrumentasi On-the-fly JaCoCo. Dan tidak ada solusi untuk mendapatkan cakupan kode di IDE.

Jadi solusinya di sini adalah memfaktorkan ulang kode sebenarnya untuk menggunakan pabrik statis yang akan mengembalikan instance kelas itu dan kemudian secara statis memalsukannya.

ACV
sumber
Setuju dengan komentar Anda.
Lathy
Itu bukan masalah di Intellij.
ACV
0

Mungkin Anda bisa langsung menggunakan

Mockito.doReturn(value).when(xxx)
jiajianchen
sumber