[英]Mock a class and a class method in python unit tests
我正在使用python的unittest.mock在Django應用程序中進行一些測試。 我想檢查一個類是否被調用,並且還調用了它的實例上的方法。
例如,給出這個簡化的示例代碼:
# In project/app.py
def do_something():
obj = MyClass(name='bob')
return obj.my_method(num=10)
這個測試來檢查發生了什么:
# In tests/test_stuff.py
@patch('project.app.MyClass')
def test_it(self, my_class):
do_something()
my_class.assert_called_once_with(name='bob')
my_class.my_method.assert_called_once_with(num=10)
測試成功地說調用了my_class
,但是沒有調用my_class.my_method
。 我知道我錯過了一些東西 - 在模擬類上嘲笑一個方法? - 但我不確定是什么或如何使它工作。
你的第二個模擬斷言需要測試你是在實例上調用my_method
,而不是在類本身上調用my_method
。
像這樣調用模擬對象,
my_class().my_method.assert_called_once_with(num=10)
^^
對您的單元測試的一個小的重構建議,以幫助您在測試中可能遇到的其他實例方法。 您可以在setUp
方法中設置全部,而不是在每個方法中模擬您的類。 這樣,當類被模擬並從該類創建一個模擬對象時,您現在可以根據需要多次使用該對象,測試類中的所有方法。
為了幫助說明這一點,我將以下示例放在一起。 評論內聯:
class MyTest(unittest.TestCase):
def setUp(self):
# patch the class
self.patcher = patch('your_module.MyClass')
self.my_class = self.patcher.start()
# create your mock object
self.mock_stuff_obj = Mock()
# When your real class is called, return value will be the mock_obj
self.my_class.return_value = self.mock_stuff_obj
def test_it(self):
do_something()
# assert your stuff here
self.my_class.assert_called_once_with(name='bob')
self.mock_stuff_obj.my_method.assert_called_once_with(num=10)
# stop the patcher in the tearDown
def tearDown(self):
self.patcher.stop()
為了提供關於這是如何放在一起的一些見解,里面setUp
方法,我們將提供功能能夠跨多個方法應用補丁作為文檔解釋這里 。
修補程序在以下兩行中完成:
# patch the class
self.patcher = patch('your_module.MyClass')
self.my_class = self.patcher.start()
最后,在這里創建模擬對象:
# create your mock object
self.mock_stuff_obj = Mock()
self.my_class.return_value = self.mock_stuff_obj
現在,您的所有測試方法都可以在所有調用中使用self.my_class
和self.mock_stuff_obj
。
這條線
my_class.my_method.assert_called_once_with(num=10)
如果my_method
是一個類方法,它將起作用。
是這樣的嗎?
否則,如果my_method
只是一個普通的實例方法,那么你需要重構函數do_something
以獲取實例變量obj
例如
def do_something():
obj = MyClass(name='bob')
return obj, obj.my_method(num=10)
# In tests/test_stuff.py
@patch('project.app.MyClass')
def test_it(self, my_class):
obj, _ = do_something()
my_class.assert_called_once_with(name='bob')
obj.my_method.assert_called_once_with(num=10)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.