Python Mock.assert\u的\u调用()未按预期工作

Python Mock.assert\u的\u调用()未按预期工作,python,django,python-unittest.mock,Python,Django,Python Unittest.mock,我有一个单元测试,我想确保我的Django自定义管理作业正在将特定消息写入其日志 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_chan

我有一个单元测试,我想确保我的Django自定义管理作业正在将特定消息写入其日志

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\u log.info.assert\u has\u calls(info\u calls,any\u 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
我做错了什么

谢谢

更新:

我必须将代码更改为:

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)

您正在将
Mock.call的结果传递给
assert\u has\u calls
。但是,
assert\u有\u调用
需要一个顶级对象


注意,在阅读文档后,我同意这一点并不太清楚。以下是以下文件:

断言已使用指定的调用调用了模拟。将检查模拟调用列表中的调用

如果任何_顺序为false,则调用必须是连续的。在指定的调用之前或之后可以有额外的调用

如果any_order为true,则调用可以是任意顺序,但它们必须全部出现在mock_调用中

mock=mock(返回值=None)
模拟(1)
模拟(2)
模拟(3)
模拟(4)
调用=[调用(2),调用(3)]
mock.assert\u有\u调用(调用)
调用=[调用(4)、调用(2)、调用(3)]
assert\u有\u调用(调用,任意顺序=True)
在该示例中,
调用
对象来自何处并不清楚。我能看到混乱

只有当您看到文档时,它才会变得更清晰(我的重点):

call()是一个帮助对象,用于生成更简单的断言,用于与call_args、call_args_list、mock_调用和method_调用进行比较call()也可以与assert\u has\u calls()一起使用。


我认为您需要将顶级对象传递给
assert\u has\u calls
,而不是
Mock.call
的结果。是的,仔细查看文档后,您似乎是对的。
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)