Apa alasan keberadaan Mock biasa ?
Penulis Mock, Michael Foord, menjawab pertanyaan yang sangat mirip di Pycon 2011 (31:00) :
T: Mengapa MagicMock membuat hal yang terpisah daripada hanya melipat kemampuan menjadi objek tiruan default?
J: Satu jawaban yang masuk akal adalah cara kerja MagicMock adalah ia mengkonfigurasi semua metode protokol ini dengan membuat Mock baru dan menyetelnya, jadi jika setiap tiruan baru membuat sekumpulan tiruan baru dan menetapkannya sebagai metode protokol dan kemudian semua protokol tersebut metode membuat lebih banyak tiruan dan mengaturnya pada metode protokol mereka, Anda punya rekursi tak terbatas ...
Bagaimana jika Anda ingin mengakses tiruan Anda sebagai objek kontainer menjadi kesalahan - Anda tidak ingin itu berfungsi? Jika setiap tiruan secara otomatis mendapatkan setiap metode protokol, maka itu menjadi jauh lebih sulit untuk melakukannya. Dan juga, MagicMock melakukan beberapa prakonfigurasi ini untuk Anda, menetapkan nilai kembalian yang mungkin tidak sesuai, jadi saya pikir akan lebih baik untuk memiliki kemudahan ini yang memiliki segalanya yang telah dikonfigurasi sebelumnya dan tersedia untuk Anda, tetapi Anda juga dapat mengambil tiruan biasa objek dan cukup konfigurasikan metode ajaib yang Anda inginkan ...
Jawaban sederhananya adalah: gunakan saja MagicMock di mana saja jika itu perilaku yang Anda inginkan.
Dengan Mock Anda dapat mengejek metode sulap tetapi Anda harus menentukannya. MagicMock memiliki "implementasi default dari sebagian besar metode ajaib." .
Jika Anda tidak perlu menguji metode sulap apa pun, Mock sudah memadai dan tidak membawa banyak hal asing ke dalam pengujian Anda. Jika Anda perlu menguji banyak metode ajaib, MagicMock akan menghemat waktu Anda.
sumber
Pertama-tama,
MagicMock
adalah subkelas dariMock
.class MagicMock(MagicMixin, Mock)
Hasilnya, MagicMock menyediakan semua yang disediakan Mock dan banyak lagi. Daripada memikirkan Mock sebagai versi MagicMock yang dipreteli, pikirkan MagicMock sebagai versi tambahan dari Mock. Ini harus menjawab pertanyaan Anda tentang mengapa Mock ada dan apa yang disediakan Mock di atas MagicMock.
Kedua, MagicMock menyediakan implementasi default dari banyak / sebagian besar metode sulap, sedangkan Mock tidak. Lihat di sini untuk informasi lebih lanjut tentang metode ajaib yang disediakan.
Beberapa contoh metode sulap yang disediakan:
>>> int(Mock()) TypeError: int() argument must be a string or a number, not 'Mock' >>> int(MagicMock()) 1 >>> len(Mock()) TypeError: object of type 'Mock' has no len() >>> len(MagicMock()) 0
Dan ini yang mungkin tidak intuitif (setidaknya tidak intuitif bagi saya):
>>> with MagicMock(): ... print 'hello world' ... hello world >>> MagicMock()[1] <MagicMock name='mock.__getitem__()' id='4385349968'>
Anda dapat "melihat" metode yang ditambahkan ke MagicMock saat metode tersebut dipanggil untuk pertama kalinya:
>>> magic1 = MagicMock() >>> dir(magic1) ['assert_any_call', 'assert_called_once_with', ...] >>> int(magic1) 1 >>> dir(magic1) ['__int__', 'assert_any_call', 'assert_called_once_with', ...] >>> len(magic1) 0 >>> dir(magic1) ['__int__', '__len__', 'assert_any_call', 'assert_called_once_with', ...]
Jadi, mengapa tidak menggunakan MagicMock setiap saat?
Pertanyaan kembali kepada Anda adalah: Apakah Anda setuju dengan penerapan metode ajaib default? Misalnya, apakah boleh untuk
mocked_object[1]
tidak melakukan kesalahan? Apakah Anda baik-baik saja dengan konsekuensi yang tidak diinginkan karena penerapan metode sihir sudah ada?Jika jawaban atas pertanyaan ini adalah ya, lanjutkan dan gunakan MagicMock. Jika tidak, tetap gunakan Mock.
sumber
Inilah yang dikatakan oleh dokumentasi resmi python :
sumber
Saya telah menemukan kasus khusus lain di mana sederhana
Mock
mungkin berubah lebih berguna daripadaMagicMock
:Membandingkan
ANY
dapat bermanfaat, misalnya, membandingkan hampir setiap kunci antara dua kamus tempat beberapa nilai dihitung menggunakan tiruan.Ini akan valid jika Anda menggunakan
Mock
:self.assertDictEqual(my_dict, { 'hello': 'world', 'another': ANY })
sementara itu akan memunculkan
AssertionError
jika Anda pernah menggunakannyaMagicMock
sumber