Bagaimana cara menguji kode berikut dengan mengolok-olok (menggunakan mengolok-olok, dekorator patch dan penjaga disediakan oleh kerangka kerja Mock Michael Foord ):
def testme(filepath):
with open(filepath, 'r') as f:
return f.read()
python
mocking
with-statement
Daryl Spitzer
sumber
sumber
Jawaban:
Cara untuk melakukan ini telah berubah di mock 0.7.0 yang akhirnya mendukung mengejek metode protokol python (metode ajaib), terutama menggunakan MagicMock:
http://www.voidspace.org.uk/python/mock/magicmock.html
Contoh mengejek terbuka sebagai manajer konteks (dari halaman contoh dalam dokumentasi tiruan):
sumber
__enter__
dan__exit__
untuk mengolok-olok objek juga - apakah pendekatan yang terakhir sudah ketinggalan zaman, atau masih berguna?file
hilang!mock_open
adalah bagian darimock
framework dan sangat mudah digunakan.patch
digunakan sebagai konteks mengembalikan objek yang digunakan untuk menggantikan yang ditambal: Anda dapat menggunakannya untuk membuat tes Anda lebih sederhana.Python 3.x
Gunakan
builtins
sebagai ganti__builtin__
.Python 2.7
mock
bukan bagian dariunittest
dan Anda harus menambal__builtin__
Kasus dekorator
Jika Anda akan menggunakan
patch
sebagai dekorator menggunakanmock_open()
hasil sebagainew
patch
argumen bisa sedikit aneh.Dalam hal ini lebih baik menggunakan
new_callable
patch
argumen dan ingat bahwa setiap argumen tambahan yangpatch
tidak digunakan akan diteruskan kenew_callable
fungsi seperti yang dijelaskan dalampatch
dokumentasi .Misalnya versi yang didekorasi untuk Python 3.x adalah:
Ingatlah bahwa dalam hal ini
patch
akan menambahkan objek tiruan sebagai argumen fungsi pengujian Anda.sumber
with patch("builtins.open", mock_open(read_data="data")) as mock_file:
dikonversi menjadi sintaksis dekorator? Saya sudah mencoba, tetapi saya tidak yakin apa yang perlu saya sampaikan@patch("builtins.open", ...)
sebagai argumen kedua.return_value
darimock_open
ke objek tiruan lain dan menegaskan mock kedua inireturn_value
), tapi itu bekerja dengan menambahkanmock_open
sebagainew_callable
.six
modul untuk memilikimock
modul yang konsisten . Tapi saya tidak tahu apakah itu memetakan jugabuiltins
dalam modul umum.Dengan versi mock terbaru, Anda dapat menggunakan pembantu mock_open yang sangat berguna :
sumber
.write
panggilan?handle.write.assert_any_call()
. Anda juga dapat menggunakanhandle.write.call_args_list
untuk mendapatkan setiap panggilan jika urutannya penting.m.return_value.write.assert_called_once_with('some stuff')
lebih baik imo. Hindari mendaftarkan panggilan.Mock.call_args_list
lebih aman daripada memanggilMock.assert_xxx
metode apa pun. Jika Anda salah mengeja salah satu dari yang terakhir, menjadi atribut Mock, mereka akan selalu diam-diam berlalu.Untuk menggunakan mock_open untuk file sederhana
read()
(snipet mock_open asli yang sudah diberikan pada halaman ini lebih diarahkan untuk menulis):Catatan sesuai dokumen untuk mock_open, ini khusus untuk
read()
, jadi tidak akan berfungsi dengan pola umum sepertifor line in f
, misalnya.Menggunakan python 2.6.6 / mock 1.0.1
sumber
for line in opened_file:
jenis kode. Saya mencoba bereksperimen dengan StringIO yang dapat diterapkan yang mengimplementasikan__iter__
dan menggunakannya bukanmy_text
, tetapi tidak berhasil.read()
jadi tidak akan berfungsi dalamfor line in opened_file
kasus Anda ; Saya telah mengedit posting untuk memperjelasfor line in f:
Dukungan @EvgeniiPuchkaryov dapat dicapai dengan mengejek nilai pengembalianopen()
sebagai objek StringIO .with open("any_string") as f: print f.read()
Jawaban teratas berguna tetapi saya sedikit memperluasnya.
Jika Anda ingin menetapkan nilai objek file Anda (
f
dalamas f
) berdasarkan argumen yang diteruskan keopen()
berikut adalah salah satu cara untuk melakukannya:Pada dasarnya,
open()
akan mengembalikan suatu objek danwith
akan memanggil__enter__()
objek itu.Untuk mengejek dengan benar, kita harus mengejek
open()
untuk mengembalikan objek tiruan. Objek tiruan itu kemudian harus mengejek__enter__()
panggilan di atasnya (MagicMock
akan melakukan ini untuk kita) untuk mengembalikan objek data / file tiruan yang kita inginkan (karenanyamm.__enter__.return_value
). Melakukan ini dengan 2 mengejek cara di atas memungkinkan kita untuk menangkap argumen yang diteruskan keopen()
dan meneruskannya kedo_something_with_data
metode kita .Saya melewati seluruh file tiruan sebagai string
open()
dan sayado_something_with_data
tampak seperti ini:Ini mengubah string menjadi daftar sehingga Anda dapat melakukan hal berikut seperti yang Anda lakukan dengan file normal:
sumber
__enter__
? Ini jelas lebih mirip hack daripada cara yang disarankan.Saya mungkin agak terlambat ke permainan, tetapi ini berhasil bagi saya ketika memanggil
open
modul lain tanpa harus membuat file baru.test.py
MyObj.py
Dengan menambal
open
fungsi di dalam__builtin__
modul kemock_open()
, saya bisa mengejek menulis ke file tanpa membuat satu.Catatan: Jika Anda menggunakan modul yang menggunakan cython, atau program Anda bergantung pada cython, Anda perlu mengimpor modul cython
__builtin__
dengan memasukkanimport __builtin__
di bagian atas file Anda. Anda tidak akan dapat mengejek universal__builtin__
jika Anda menggunakan cython.sumber
import __builtin__
modul pengujian saya. Artikel ini membantu memperjelas mengapa teknik ini bekerja sebaik itu: ichimonji10.name/blog/6Untuk menambal fungsi buka () bawaan dengan unittest:
Ini berfungsi untuk tambalan untuk membaca konfigurasi json.
Objek yang dipermainkan adalah objek io.TextIOWrapper yang dikembalikan oleh fungsi open ()
sumber
Jika Anda tidak memerlukan file lebih jauh, Anda dapat menghias metode pengujian:
sumber