Mock.assert_has_calls () не работает должным образом - PullRequest
0 голосов
/ 03 августа 2020

У меня есть этот модульный тест, где я хочу убедиться, что мое задание Django настраиваемого управления записывает в свой журнал определенные c сообщения.

from unittest.mock import Mock, patch

...

    @override_settings(HR_SYNC_DATA_DIR=f"{settings.BASE_DIR}/core/management/tests/HR_SYNC_DATA_DIR")
    @patch('core.management.commands.process_hr_changes.log')
    @patch('core.management.commands.process_hr_changes.requests.get')
    def test_sync_users2(self, mock_get, mock_log):
        #
        # Load our Mock data
        #
        test_data_dir = f"{settings.BASE_DIR}/core/management/tests/TEST_DATA_DIR"
        get_mocks = []
        for filename in glob.glob(path.join(test_data_dir, 'test-data-hrdata_underrun_page_*.json')):
            with open(filename, "r") as infile:
                mock_response = Mock(ok=True)
                mock_response.json.return_value = json.load(infile)
                mock_response.status_code = status.HTTP_200_OK
                get_mocks.append(mock_response)
        mock_get.side_effect = get_mocks
        with self.assertRaises(CommandError) as context:
            call_command('process_hr_changes')
        print(context.exception)
        self.assertEqual('percent change is -0.125 and delta_pct is 0.1. Lifecycle is dev.', context.exception.args[0])
        mock = Mock(return_value=None)
        info_calls = [
            mock.call('rehires = 0 new hires = 0 terminations = 5.'),
            mock.call('process_hr_changes args are: delta_pct 0.1 how_many_hours_back 24 dry_run False debug is False verbose is False'),
            mock.call('test: startup'),
            mock.call('Removing directory /apps/core/management/tests/HR_SYNC_DATA_DIR.'),
            mock.call('Creating directory /apps/core/management/tests/HR_SYNC_DATA_DIR.'),
            mock.call('percent change is -0.125 and delta_pct is 0.1.'),
        ]
        for mock_call in mock_log.info.mock_calls:
            print(mock_call)
        mock_log.info.assert_has_calls(info_calls, any_order=True)

Когда я запускаю этот тест, он не работает на mock_log.info.assert_has_calls(info_calls, any_order=True) с этим сообщением:

AssertionError: (<MagicMock name='log.call()' id='140711932625744'>, <MagicMock name='log.call()' id='140711932625744'>, <MagicMock name='log.call()' id='140711932625744'>, <MagicMock name='log.call()' id='140711932625744'>, <MagicMock name='log.call()' id='140711932625744'>, <MagicMock name='log.call()' id='140711932625744'>) not all found in call list

Я также вижу этот вывод из моего оператора печати:

call('process_hr_changes args are: delta_pct 0.1 how_many_hours_back 24 dry_run False debug is False verbose is False')
call('test: startup')
call('Removing directory /apps/core/management/tests/HR_SYNC_DATA_DIR.')
call('Creating directory /apps/core/management/tests/HR_SYNC_DATA_DIR.')
call('rehires = 0 new hires = 0 terminations = 5.')
call('percent change is -0.125 and delta_pct is 0.1.')

Что я делаю не так?

Спасибо

ОБНОВЛЕНИЕ:

Мне пришлось изменить свой код на этот:

from unittest.mock import Mock, patch, call  # need to import call.

...

        info_calls = [
            call('rehires = 0 new hires = 0 terminations = 5.'),
            call('process_hr_changes args are: delta_pct 0.1 how_many_hours_back 24 dry_run False debug is False verbose is False'),
            call('test: startup'),
            call('Removing directory /apps/core/management/tests/HR_SYNC_DATA_DIR.'),
            call('Creating directory /apps/core/management/tests/HR_SYNC_DATA_DIR.'),
            call('percent change is -0.125 and delta_pct is 0.1.'),

        ]
        mock_log.info.assert_has_calls(info_calls, any_order=True)

1 Ответ

1 голос
/ 03 августа 2020

Вы передаете результат Mock.call на assert_has_calls. Но assert_has_calls ожидает объект верхнего уровня call.

Обратите внимание, после прочтения документации я согласен, что это не слишком ясно. Вот документы для assert_has_calls:

утверждают, что макет был вызван с указанными вызовами. Список mock_calls проверяется на наличие вызовов.

Если any_order имеет значение false, тогда вызовы должны быть последовательными. Могут быть дополнительные вызовы до или после указанных вызовов.

Если any_order истинно, тогда вызовы могут быть в любом порядке, но все они должны появляться в mock_calls.

mock = Mock(return_value=None)
mock(1)
mock(2)
mock(3)
mock(4)
calls = [call(2), call(3)]
mock.assert_has_calls(calls)
calls = [call(4), call(2), call(3)]
mock.assert_has_calls(calls, any_order=True)

Непонятно, откуда взялся объект call в этом примере. Я вижу путаницу.

Только когда вы видите документацию call, она становится немного яснее (выделено мной):

call ( ) - вспомогательный объект для создания более простых утверждений, для сравнения с call_args, call_args_list, mock_calls и method_calls. call () также может использоваться с assert_has_calls () .

...