Передайте параметр в функцию side_effect для исправления в unittest.mock - PullRequest
0 голосов
/ 22 января 2019

Я использую patch из unittest.mock, чтобы изменить поведение удаленного вызова API в моем тесте.

У меня есть три разные функции, которые возвращают три разных json файла, которые представляют макетданные, которые будут возвращены из API.Для каждого ложного вызова API я устанавливаю side_effect в качестве одной из этих функций.Этот шаблон не СУХОЙ, но я не знаю, как передать параметр в 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 голосов
/ 22 января 2019

Использование лямбда-функции:

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()
0 голосов
/ 22 января 2019

Я думаю, что самый простой способ сделать это - установить 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, и он будет вести себя как положено.

...