PowerMockito memalsukan metode statis tunggal dan mengembalikan objek

98

Saya ingin mengejek metode statis m1 dari kelas yang berisi 2 metode statis, m1 dan m2. Dan saya ingin metode m1 mengembalikan objek.

Saya mencoba yang berikut ini

1)

PowerMockito.mockStatic(Static.class, new Answer<Long>() {
         @Override
         public Long answer(InvocationOnMock invocation) throws Throwable {
            return 1000l;
         }
      });

Ini memanggil m1 dan m2, yang memiliki tipe pengembalian berbeda, sehingga memberikan kesalahan ketidakcocokan tipe pengembalian.

2) PowerMockito.when(Static.m1(param1, param2)).thenReturn(1000l); Tapi ini tidak dipanggil saat m1 dijalankan.

3) PowerMockito.mockPartial(Static.class, "m1"); Memberikan kesalahan compiler bahwa mockP Partial tidak tersedia, yang saya dapatkan dari http://code.google.com/p/powermock/wiki/MockitoUsage .

pengguna1393653
sumber

Jawaban:

136

Yang ingin Anda lakukan adalah kombinasi dari bagian 1 dan semua dari 2.

Anda perlu menggunakan PowerMockito.mockStatic untuk mengaktifkan pemalsuan statis untuk semua metode statis suatu kelas. Ini berarti memungkinkan untuk menghentikan mereka menggunakan sintaks when-thenReturn.

Tetapi kelebihan 2-argumen dari mockStatic yang Anda gunakan menyediakan strategi default untuk apa yang harus dilakukan Mockito / PowerMock ketika Anda memanggil metode yang belum secara eksplisit dihentikan pada contoh tiruan.

Dari javadoc :

Membuat tiruan kelas dengan strategi tertentu sebagai jawaban atas interaksinya. Ini fitur yang cukup canggih dan biasanya Anda tidak membutuhkannya untuk menulis tes yang layak. Namun, ini dapat membantu saat bekerja dengan sistem lama. Ini adalah jawaban default sehingga hanya akan digunakan jika Anda tidak menghentikan pemanggilan metode.

The bawaan Strategi Stubbing default adalah untuk hanya nol kembali, 0 atau salah untuk objek, jumlah dan boolean metode dihargai. Dengan menggunakan overload 2-arg, Anda mengatakan "Tidak, tidak, tidak, secara default gunakan metode jawaban subkelas Answer ini untuk mendapatkan nilai default. Ini mengembalikan Long, jadi jika Anda memiliki metode statis yang mengembalikan sesuatu yang tidak kompatibel dengan Lama, ada masalah.

Sebagai gantinya, gunakan versi 1-arg dari mockStatic untuk mengaktifkan stubbing metode statis, lalu gunakan when-thenReturn untuk menentukan apa yang harus dilakukan untuk metode tertentu. Sebagai contoh:

import static org.mockito.Mockito.*;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;

class ClassWithStatics {
  public static String getString() {
    return "String";
  }

  public static int getInt() {
    return 1;
  }
}

@RunWith(PowerMockRunner.class)
@PrepareForTest(ClassWithStatics.class)
public class StubJustOneStatic {
  @Test
  public void test() {
    PowerMockito.mockStatic(ClassWithStatics.class);

    when(ClassWithStatics.getString()).thenReturn("Hello!");

    System.out.println("String: " + ClassWithStatics.getString());
    System.out.println("Int: " + ClassWithStatics.getInt());
  }
}

Metode statis bernilai String diberi stub untuk mengembalikan "Halo!", Sedangkan metode statis bernilai int menggunakan stub default, mengembalikan 0.

Tom Tresansky
sumber
1
Apakah tidak perlu diputar ulang?
Balaji Boggaram Ramanarayan
Hmm ... sepertinya begitu. Mungkin PowerMockito memutar ulang PowerMock untuk Anda? Saya juga bertanya-tanya tentang itu.
djangofan
3
Tetapi bagaimana jika saya perlu memastikan bahwa beberapa metode statis dipanggil dengan argumen yang tepat?
elTomato
6
The @PrepareForTestanotasi harus menjadi kelas yang memanggil metode statis, bukan kelas di mana metode statis.
Hazel Troost
5
@HazelTroost - Tidak, OP benar. Ini adalah kelas yang berisi metode statis yang harus disiapkan untuk pengujian. Jadi @PrepareForTest(ClassWithStatics.class)benar.
arry36