assert_has_calls
adalah pendekatan lain untuk masalah ini.
Dari dokumen:
assert_has_calls (panggilan, any_order = Salah)
menegaskan mock telah dipanggil dengan panggilan yang ditentukan. Daftar mock_calls diperiksa untuk panggilan.
Jika any_order salah (default) maka panggilan harus berurutan. Mungkin ada panggilan tambahan sebelum atau setelah panggilan yang ditentukan.
Jika any_order Benar maka panggilan bisa dalam urutan apa pun, tetapi semuanya harus muncul di mock_calls.
Contoh:
>>> from unittest.mock import call, Mock
>>> mock = Mock(return_value=None)
>>> mock(1)
>>> mock(2)
>>> mock(3)
>>> mock(4)
>>> calls = [call(2), call(3)]
>>> mock.assert_has_calls(calls)
>>> calls = [call(4), call(2), call(3)]
>>> mock.assert_has_calls(calls, any_order=True)
Sumber: https://docs.python.org/3/library/unittest.mock.html#unittest.mock.Mock.assert_has_calls
tuple
:isinstance(mock.call(1), tuple)
memberiTrue
. Mereka juga menambahkan beberapa metode dan atribut.side_effect
Biasanya, saya tidak peduli dengan urutan panggilan, hanya saja itu terjadi. Dalam hal ini, saya menggabungkan
assert_any_call
dengan pernyataan tentangcall_count
.Saya merasa melakukannya dengan cara ini agar lebih mudah dibaca dan dipahami daripada sejumlah besar panggilan masuk ke satu metode.
Jika Anda benar-benar peduli dengan pesanan atau mengharapkan beberapa panggilan identik,
assert_has_calls
mungkin lebih tepat.Edit
Sejak saya memposting jawaban ini, saya telah memikirkan kembali pendekatan saya pada pengujian secara umum. Saya pikir itu layak disebutkan bahwa jika pengujian Anda mendapatkan ini rumit, Anda mungkin menguji secara tidak tepat atau memiliki masalah desain. Mock dirancang untuk menguji komunikasi antar-objek dalam desain berorientasi objek. Jika desain Anda tidak berorientasi pada objek (seperti dalam lebih prosedural atau fungsional), tiruan itu mungkin sama sekali tidak pantas. Anda juga mungkin memiliki terlalu banyak hal yang terjadi di dalam metode ini, atau Anda mungkin menguji rincian internal yang sebaiknya tidak diolok-olok. Saya mengembangkan strategi yang disebutkan dalam metode ini ketika kode saya tidak terlalu berorientasi objek, dan saya percaya saya juga menguji detail internal yang sebaiknya dibiarkan tidak terbongkar.
sumber
do() if TEST_ENV=='prod' else dont()
), dicapai dengan mudah dengan mengejek seperti yang Anda sarankan. efek samping dari hal ini adalah untuk mempertahankan tes per versi (katakanlah perubahan kode antara google search api v1 dan v2, kode Anda akan menguji versi 1 tidak peduli apa)Anda dapat menggunakan
Mock.call_args_list
atribut untuk membandingkan parameter dengan panggilan metode sebelumnya. Sehubungan denganMock.call_count
atribut harus memberi Anda kontrol penuh.sumber
assert_has_calls
hanya memeriksa apakah panggilan yang diharapkan telah dilakukan, tetapi tidak jika itu adalah satu-satunya.Saya selalu harus melihat ini berulang kali, jadi inilah jawaban saya.
Menyatakan beberapa panggilan metode pada objek yang berbeda dari kelas yang sama
Misalkan kita memiliki kelas tugas berat (yang ingin kita tiru):
berikut adalah beberapa kode yang menggunakan dua instance
HeavyDuty
kelas:Sekarang, ini adalah test case untuk
heavy_work
fungsinya:Kami mengejek
HeavyDuty
kelas denganMockHeavyDuty
. Untuk menegaskan panggilan metode yang datang dari setiapHeavyDuty
contoh, kita harus merujukMockHeavyDuty.return_value.assert_has_calls
, bukanMockHeavyDuty.assert_has_calls
. Selain itu, dalam daftarexpected_calls
kami harus menentukan nama metode yang kami minati untuk menyatakan panggilan. Jadi daftar kami dibuat dari panggilancall.do_work
, bukan hanyacall
.Melatih uji kasus menunjukkan kepada kita bahwa itu berhasil:
Jika kami memodifikasi
heavy_work
fungsinya, pengujian gagal dan menghasilkan pesan kesalahan yang membantu:Membuat beberapa panggilan ke suatu fungsi
Untuk kontras dengan yang di atas, berikut adalah contoh yang menunjukkan cara mengejek banyak panggilan ke suatu fungsi:
Ada dua perbedaan utama. Yang pertama adalah bahwa ketika mengejek suatu fungsi, kami mengatur panggilan yang kami harapkan menggunakan
call
, bukannya menggunakancall.some_method
. Yang kedua adalah bahwa kita sebutassert_has_calls
padamock_work_function
, bukan padamock_work_function.return_value
.sumber