Modul A
termasuk import B
di atasnya. Namun di bawah kondisi pengujian saya ingin mengejek B
di A
(mock A.B
) dan benar-benar menahan diri dari impor B
.
Bahkan, B
tidak dipasang di lingkungan pengujian dengan sengaja.
A
adalah unit yang sedang diuji. Saya harus mengimpor A
dengan semua fungsinya. B
adalah modul yang perlu saya tiru. Tetapi bagaimana saya bisa mengejek B
dalam A
dan berhenti A
mengimpor yang asli B
, jika hal pertama yang A
dilakukan adalah mengimpor B
?
(Alasan B tidak diinstal adalah bahwa saya menggunakan pypy untuk pengujian cepat dan sayangnya B belum kompatibel dengan pypy.)
Bagaimana ini bisa dilakukan?
sumber
Mock
tidak akan menambal beberapa atribut ajaib (__%s__
) seperti__name__
.sys.modules['B'] = None
tetapi tampaknya tidak berhasil.mock
dan kemudian memanggilmock.Mock()
Builtin
__import__
dapat diejek dengan perpustakaan 'mock' untuk kontrol lebih lanjut:Say
A
sepertinya:A.a()
pengembalianb_mock.func()
yang bisa diejek juga.Catatan untuk Python 3: Sebagaimana dinyatakan dalam changelog untuk 3.0 ,
__builtin__
sekarang dinamaibuiltins
:Kode dalam jawaban ini berfungsi dengan baik jika Anda mengganti
__builtin__
denganbuiltins
untuk Python 3.sumber
import_mock
dipanggil untukimport A
, tetapi tidak untuk apa pun yang diimpor.ImportError: No module named '__builtin__'
__builtin__
__builtin__
denganbuiltins
untuk python3 ( docs.python.org/3/whatsnew/3.0.html?highlight=__builtin__ )Mudah, cukup mengejek perpustakaan di sys.modules sebelum diimpor:
dan kemudian, selama
A
tidak bergantung pada tipe data tertentu yang dikembalikan dari objek B:seharusnya hanya bekerja.
Anda juga bisa mengejek
import A.B
:Ini berfungsi bahkan jika Anda memiliki submodula, tetapi Anda ingin mengejek setiap modul. Katakan Anda memiliki ini:
Untuk mengejek, cukup lakukan di bawah ini sebelum modul yang berisi di atas diimpor:
(Pengalaman saya: Saya memiliki ketergantungan yang bekerja pada satu platform, Windows, tetapi tidak bekerja di Linux, di mana kami menjalankan tes harian kami. Jadi saya perlu mengejek ketergantungan untuk tes kami. Untungnya itu adalah kotak hitam, jadi Saya tidak perlu mengatur banyak interaksi.)
Efek Samping Mengejutkan
Tambahan: Sebenarnya, saya perlu mensimulasikan efek samping yang memerlukan waktu. Jadi saya perlu metode objek untuk tidur sebentar. Itu akan bekerja seperti ini:
Dan kemudian kode membutuhkan waktu untuk berjalan, seperti metode yang sebenarnya.
sumber
Saya menyadari bahwa saya agak terlambat ke pesta di sini, tapi ini cara yang agak gila untuk mengotomatisasi ini dengan
mock
perpustakaan:(inilah contoh penggunaan)
Alasan mengapa hal ini sangat rumit adalah ketika suatu impor terjadi pada dasarnya python melakukan ini (ambil contoh
from herp.derp import foo
)sys.modules['herp']
ada Lain impor saja. Jika masih belumImportError
sys.modules['herp.derp']
ada Lain impor saja. Jika masih belumImportError
foo
darisys.modules['herp.derp']
. LainImportError
foo = sys.modules['herp.derp'].foo
Ada beberapa kerugian untuk solusi yang diretas bersama ini: Jika ada hal lain yang bergantung pada hal-hal lain di jalur modul, sekrupkan ini. Ini juga hanya berfungsi untuk barang yang sedang diimpor inline seperti
atau
sumber
Jawaban Aaron Hall bekerja untuk saya. Hanya ingin menyebutkan satu hal penting,
jika di dalam
A.py
kamu lakukanfrom B.C.D import E
maka di dalam
test.py
kamu harus mengejek setiap modul di sepanjang jalan, jika tidak kamu dapatkanImportError
sumber
Saya menemukan cara yang bagus untuk mengejek impor dengan Python. Ini adalah solusi Erica Zaadi yang ditemukan di sini yang saya gunakan di dalam aplikasi Django saya .
Saya punya kelas
SeatInterface
yang merupakan antarmuka keSeat
kelas model. Jadi di dalamseat_interface
modul saya, saya memiliki impor seperti itu:Saya ingin membuat tes terisolasi untuk
SeatInterface
kelas denganSeat
kelas mengejekFakeSeat
. Masalahnya adalah - bagaimana Anda menjalankan tes offline, di mana aplikasi Django sedang down. Saya memiliki kesalahan di bawah ini:Solusinya adalah:
Dan kemudian uji ajaib berjalan OK :)
sumber
Jika Anda melakukannya,
import ModuleB
Anda benar-benar memanggil metode builtin__import__
sebagai:Anda bisa menimpa metode ini dengan mengimpor
__builtin__
modul dan membuat pembungkus di sekitar__builtin__.__import__
metode ini. Atau Anda bisa bermain denganNullImporter
pengait dariimp
modul. Menangkap pengecualian dan mengejek modul / kelas Anda diexcept
-block.Menunjuk ke dokumen yang relevan:
docs.python.org:
__import__
Mengakses internal impor dengan Modul imp
Saya harap ini membantu. Jadilah SANGAT disarankan bahwa Anda melangkah ke batas yang lebih misterius dari pemrograman python dan bahwa a) pemahaman yang kuat tentang apa yang benar-benar ingin Anda capai dan b) pemahaman menyeluruh tentang implikasi itu penting.
sumber