将参数传递给side_effect函数以在unittest.mock中进行修补

时间:2019-01-21 21:56:31

标签: python unit-testing python-unittest python-mock

我正在使用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函数进行硬编码。

2 个答案:

答案 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,它将按预期运行。