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):
In [1]: class HeavyDuty(object):
...: def __init__(self):
...: import time
...: time.sleep(2) # <- Spends a lot of time here
...:
...: def do_work(self, arg1, arg2):
...: print("Called with %r and %r" % (arg1, arg2))
...:
berikut adalah beberapa kode yang menggunakan dua instance HeavyDuty
kelas:
In [2]: def heavy_work():
...: hd1 = HeavyDuty()
...: hd1.do_work(13, 17)
...: hd2 = HeavyDuty()
...: hd2.do_work(23, 29)
...:
Sekarang, ini adalah test case untuk heavy_work
fungsinya:
In [3]: from unittest.mock import patch, call
...: def test_heavy_work():
...: expected_calls = [call.do_work(13, 17),call.do_work(23, 29)]
...:
...: with patch('__main__.HeavyDuty') as MockHeavyDuty:
...: heavy_work()
...: MockHeavyDuty.return_value.assert_has_calls(expected_calls)
...:
Kami mengejek HeavyDuty
kelas dengan MockHeavyDuty
. Untuk menegaskan panggilan metode yang datang dari setiap HeavyDuty
contoh, kita harus merujuk MockHeavyDuty.return_value.assert_has_calls
, bukan MockHeavyDuty.assert_has_calls
. Selain itu, dalam daftar expected_calls
kami harus menentukan nama metode yang kami minati untuk menyatakan panggilan. Jadi daftar kami dibuat dari panggilan call.do_work
, bukan hanya call
.
Melatih uji kasus menunjukkan kepada kita bahwa itu berhasil:
In [4]: print(test_heavy_work())
None
Jika kami memodifikasi heavy_work
fungsinya, pengujian gagal dan menghasilkan pesan kesalahan yang membantu:
In [5]: def heavy_work():
...: hd1 = HeavyDuty()
...: hd1.do_work(113, 117) # <- call args are different
...: hd2 = HeavyDuty()
...: hd2.do_work(123, 129) # <- call args are different
...:
In [6]: print(test_heavy_work())
---------------------------------------------------------------------------
(traceback omitted for clarity)
AssertionError: Calls not found.
Expected: [call.do_work(13, 17), call.do_work(23, 29)]
Actual: [call.do_work(113, 117), call.do_work(123, 129)]
Membuat beberapa panggilan ke suatu fungsi
Untuk kontras dengan yang di atas, berikut adalah contoh yang menunjukkan cara mengejek banyak panggilan ke suatu fungsi:
In [7]: def work_function(arg1, arg2):
...: print("Called with args %r and %r" % (arg1, arg2))
In [8]: from unittest.mock import patch, call
...: def test_work_function():
...: expected_calls = [call(13, 17), call(23, 29)]
...: with patch('__main__.work_function') as mock_work_function:
...: work_function(13, 17)
...: work_function(23, 29)
...: mock_work_function.assert_has_calls(expected_calls)
...:
In [9]: print(test_work_function())
None
Ada dua perbedaan utama. Yang pertama adalah bahwa ketika mengejek suatu fungsi, kami mengatur panggilan yang kami harapkan menggunakan call
, bukannya menggunakan call.some_method
. Yang kedua adalah bahwa kita sebut assert_has_calls
pada mock_work_function
, bukan pada mock_work_function.return_value
.