ฉันต้องดูครั้งนี้ซ้ำแล้วซ้ำอีกดังนั้นนี่คือคำตอบของฉัน
การยืนยันการเรียกใช้หลายวิธีบนวัตถุที่แตกต่างของคลาสเดียวกัน
สมมติว่าเรามีชั้นเรียนหนัก (ซึ่งเราต้องการเยาะเย้ย):
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))
...:
นี่คือรหัสบางส่วนที่ใช้สองอินสแตนซ์ของ HeavyDuty
คลาส:
In [2]: def heavy_work():
...: hd1 = HeavyDuty()
...: hd1.do_work(13, 17)
...: hd2 = HeavyDuty()
...: hd2.do_work(23, 29)
...:
ตอนนี้นี่คือกรณีทดสอบสำหรับheavy_work
ฟังก์ชั่น:
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)
...:
เราจะเยาะเย้ยชั้นเรียนกับHeavyDuty
MockHeavyDuty
วิธีการที่จะยืนยันการโทรมาจากทุกHeavyDuty
ตัวอย่างเช่นเราต้องดูแทนMockHeavyDuty.return_value.assert_has_calls
MockHeavyDuty.assert_has_calls
นอกจากนี้ในรายการexpected_calls
เราต้องระบุชื่อวิธีการที่เราสนใจในการยืนยันการโทร ดังนั้นรายการของเราจะทำจากการโทรไปเมื่อเทียบกับเพียงcall.do_work
call
การออกกำลังกายกรณีทดสอบแสดงให้เราเห็นว่ามันประสบความสำเร็จ:
In [4]: print(test_heavy_work())
None
หากเราปรับเปลี่ยนheavy_work
ฟังก์ชั่นการทดสอบล้มเหลวและสร้างข้อความแสดงข้อผิดพลาดที่เป็นประโยชน์:
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)]
การยืนยันการเรียกหลายฟังก์ชั่น
นี่คือตัวอย่างที่แสดงวิธีเยาะเย้ยการเรียกหลายฟังก์ชั่น:
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
มีความแตกต่างที่สำคัญสองประการ คนแรกคือว่าเมื่อเยาะเย้ยการตั้งค่าฟังก์ชั่นที่เราคาดว่าสายของเราโดยใช้แทนการใช้call
call.some_method
คนที่สองคือการที่เราเรียกassert_has_calls
บนแทนในmock_work_function
mock_work_function.return_value