Как получить кол-во вызовов с помощью Mock @patch?

Я пишу единичный тест для некоторой библиотеки, над которой мы работаем. Эта библиотека использует requests.post() для выполнения POST-запросов HTTP на внешний сервер.

Внутри моего UT я, очевидно, не хочу связываться с реальным сервером, но издеваться над ответом.

Для этого я написал функцию, которая выглядит следующим образом:

def mocked_post(url, headers, data, **kwargs):
    response = Mock()

    # Some logic, irrelevant here.

    return response

И я исправил эту функцию вокруг моего модульного тестового класса:

@patch('mylib.requests.post', mocked_post)
class MyTest(TestCase):

    def test_foo(self):
        # Some test logic

Это прекрасно работает.

Теперь я хотел бы получить количество звонков в мою издеваемую функцию. Я пробовал mocked_post.call_count но этого не существует. Я попытался найти это свойство на множестве разных объектов (включая mylib.requests.post), но пока не повезло.

Как я могу получить доступ к call_count для этой call_count функции?

Ответ 1

Я бы не использовал mocked_post в качестве new аргумента здесь. Вместо этого я установил атрибут side_effect нового Mock:

@patch('mylib.requests.post')
class MyTest(TestCase):

    def test_foo(self, post_mock):
        post_mock.side_effect = mocked_post

        # Some test logic

        self.assertEqual(post_mock.call_count, 3)

Теперь у вас есть объект Mock который patch генерирует для вас в качестве аргумента для всех ваших методов тестирования, и вы можете таким образом проверить, сколько раз был вызван макет.

Вы также должны установить атрибут side_effect в декораторе, чтобы применить ко всем тестам:

@patch('mylib.requests.post', side_effect=mocked_post)
class MyTest(TestCase):

    def test_foo(self, post_mock):
        # Some test logic

        self.assertEqual(post_mock.call_count, 3)

Однако у вас все еще есть проблемы с доступом к возвращенному объекту response; вы можете вернуть mock.DEFAULT из mocked_post вместо того, чтобы создавать его в функции, чтобы затем вы могли использовать post_mock.return_value для дальнейших утверждений о возвращаемом объекте.