[英]Difference between side_effect within function vs side_effect in decorator
[英]What is the difference between mocking with @patch() with and without side_effect?
我有一個script.py
文件:
# in script.py
def my_basic_function(value, c):
return c(value).words()
class BasicClass:
def __init__(self, val):
self.val = val
def words():
return self.val
和一個test.py
文件:
# in test.py
from mock import patch
from script import my_basic_function, BasicClass
def third_function(self,):
return "not {}".format(self.val)
def fourth_function():
return "not ponies"
def init_mock(self, val):
self.val = val
@patch('script.BasicClass.words', third_function)
@patch('script.BasicClass.__init__', init_mock)
def test_my_basic_function():
assert my_basic_function("ponies", BasicClass) == "not ponies"
我可以成功地從命令行使用pytest test.py
運行。
如果我想在我的@patch
使用side_effect
,我必須做一些不同的事情:
@patch('script.BasicClass.words', side_effect = fourth_function)
@patch('script.BasicClass.__init__', init_mock)
def test_my_basic_function(amock):
assert my_basic_function("ponies", BasicClass) == "not ponies"
即,我必須:
test_my_basic_function
添加一個我從未使用過的參數。fourth_function
而不是third_function
,因為我不能使用任何類實例變量。這兩種方式打補丁有什么區別?
您不需要為您正在做的事情打補丁(示例 A )。 您正在傳入參數 c,您知道它是 BasicClass 的類,因此不需要補丁。 如果您在正在測試的函數中引入了函數調用或對象初始化,而您不想實際發生,則需要一個補丁。
使用@patch
我們應該使用 kwarg side_effect
來模擬引發異常,而不是調用其他函數。 如果我們想模擬函數的返回值,請使用 kwarg return_value
。 如果我們只想模擬一個函數,那么我們只需使用@patch
而不使用任何 kwargs。 當我們使用補丁作為裝飾器時,我們需要將它們傳遞給函數。 的確,它們可以未被使用,但我們應該將它們與諸如assert_called_once
或assert_called_once_with
類的模擬函數一起使用,以確保您的補丁按預期工作。 請參見示例 B
==============示例A==================
import unittest
def my_basic_function(value, c):
return c(value).words()
class BasicClass:
def __init__(self, val):
self.val = val
def words(self):
return self.val
class TestMyBasicFunction(unittest.TestCase):
def test_my_basic_class(self):
value = my_basic_function("jeremy", BasicClass)
self.assertEqual("jeremy", value)
def test_my_basic_class_wrong(self):
value = my_basic_function("jeremy", BasicClass)
self.assertNotEqual("w33b", value)
============示例B======================
import unittest
from unittest.mock import patch
def ensure_str(value):
try:
return str(value)
except Exception:
raise TypeError
def my_basic_function(value, c):
value = ensure_str(value)
return c(value).words()
class BasicClass:
def __init__(self, val):
self.val = val
def words(self):
return self.val
class TestMyBasicFunction(unittest.TestCase):
@patch('script.ensure_str', return_value="jeremy")
def test_return_value(self, ensure_str_mock):
value = my_basic_function("jeremy", BasicClass)
ensure_str_mock.assert_called_once_with("jeremy")
self.assertEqual("jeremy", value)
@patch('script.ensure_str')
def test_no_return_value(self, ensure_str_mock):
value = my_basic_function("jeremy", BasicClass)
self.assertEqual(ensure_str_mock(), value)
@patch('script.ensure_str', side_effect=TypeError)
def test_side_effect(self, ensure_str_mock):
with self.assertRaises(TypeError):
value = my_basic_function({'apple': 'sauce'}, BasicClass)
ensure_str_mock.assert_called_once_with({'apple': 'sauce'})
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.