简体   繁体   English

Mock.assert_has_calls() 没有按预期工作

[英]Mock.assert_has_calls() not working as expected

I have this unit test where I want to ensure my Django custom management job is writing specific messages to its log.我有这个单元测试,我想确保我的 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)

When I run this test it fails on the mock_log.info.assert_has_calls(info_calls, any_order=True) statement with this message:当我运行此测试时,它在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

I also see this output from my print statement:我还从我的打印语句中看到了这个 output:

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.')

What am I doing wrong?我究竟做错了什么?

Thanks谢谢

UPDATE:更新:

I had to change my code to this:我不得不将我的代码更改为:

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)

You are passing the result of Mock.call to assert_has_calls .您将Mock.call的结果传递给assert_has_calls But, assert_has_calls expects a top-levelcall object.但是, assert_has_calls需要一个顶级call object。


Note, after reading the docs I concur this is not overly clear.请注意,在阅读文档后,我同意这并不太清楚。 Here's the docs for assert_has_calls :这是assert_has_calls的文档:

assert the mock has been called with the specified calls.断言已使用指定的调用调用了模拟。 The mock_calls list is checked for the calls.检查 mock_calls 列表中的调用。

If any_order is false then the calls must be sequential.如果 any_order 为假,则调用必须是顺序的。 There can be extra calls before or after the specified calls.在指定的调用之前或之后可以有额外的调用。

If any_order is true then the calls can be in any order, but they must all appear in mock_calls.如果 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)

It's not clear where the call object comes from in that example.不清楚该示例中call object 的来源。 I can see the confusion.我可以看到混乱。

It's only when you see thecall documentation that it gets a bit clearer (emphasis mine):只有当您看到call文档时,它才会变得更加清晰(强调我的):

call() is a helper object for making simpler assertions, for comparing with call_args, call_args_list, mock_calls and method_calls. call() 是一个帮助器 object,用于进行更简单的断言,用于与 call_args、call_args_list、mock_calls 和 method_calls 进行比较。 call() can also be used with assert_has_calls() . call() 也可以与 assert_has_calls() 一起使用

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM