我正在使用patch
中的unittest.mock
来更改测试中远程API调用的行为。
我有三个不同的函数,它们返回三个不同的json
文件,这些文件表示要从API返回的模拟数据。对于每个模拟api调用,我将side_effect
设置为以下功能之一。这种模式不是DRY,但是我不知道如何将参数传递给side_effect
函数。
三个模拟api调用函数如下:
def mock_api_call_1():
with open('path/to/mock_1.json') as f:
mock_data = json.load(f)
return mock_data
这是我的考试
class MyTest(TestCase):
def test_api(self):
with patch('mymodule.utils.api_call', side_effect=mock_api_call_1):
do_crud_operations()
self.assertEqual(MyModel.objects.all().count(), 10)
with patch('mymodule.utils.api_call', side_effect=mock_api_call_2):
do_crud_operations()
self.assertEqual(MyModel.objects.all().count(), 11)
如何重构此代码,以便能够将参数传递给side_effect
(而不是mock_call(1)
(mock_call_1
)。
从unittest docs中,我看到了:
side_effect:每当调用Mock时都要调用的函数。看到 side_effect属性。对于引发异常或 动态更改返回值。该函数用 与模拟相同的参数,除非返回DEFAULT,否则返回 该函数的值用作返回值。
我看到传递给side_effect
的函数采用了与模拟相同的参数,但是我仍然不确定如何最好地使用模拟来完成此操作。我最终将要添加更多的测试用例,所以我不想对不同的mock_api_call
函数进行硬编码。
答案 0 :(得分:1)
使用lambda函数:
from unittest import TestCase, main
from unittest.mock import Mock, patch
import sys
def mock_api_call(x):
print(x)
class MyTest(TestCase):
def test_api(self):
with patch('sys.exit',
side_effect=lambda x: mock_api_call(x)) as m:
m(0)
sys.exit(0)
m(1)
sys.exit(1)
if __name__ == '__main__':
main()
答案 1 :(得分:0)
我认为最简单的方法是将side_effect
设置为返回函数的函数。
def mock_call(num):
def wrapper():
with open("path/to/mock_{num}.json") as f:
data = json.load(f)
return data
return wrapper
现在我可以将mock_call(1)
传递给side_effect
,它将按预期运行。