【问题标题】:mock object library ANY not working as expected模拟对象库 ANY 没有按预期工作
【发布时间】:2021-07-18 02:21:58
【问题描述】:

我目前正在尝试模拟对服务器的补丁请求,并且正在尝试使用模拟对象库中的 ANY 属性。我有以下代码:

@patch('path_to_patch.patch')
def test_job_restarted_succesfully(mock_patch):
   make_patch_call()
   mock_patch.assert_called_with(url=ANY, payload=ANY, callback=ANY, async_run=ANY, kwargs=ANY)

我收到以下错误:

AssertionError: Expected call: patch(async_run=<ANY>, callback=<ANY>, kwargs=<ANY>, payload=<ANY>, url=<ANY>)
E           Actual call: patch(async_run=True, callback=<function JobSvc.send_job_patch_request.<locals>.retry_on_404 at 0x000002752B873168>, payload={'analyzer': {'state': 'started'}, 'meta': {}}, svc_auth=UUID('40ed1a00-a51f-11eb-b1ed-b46bfc345269'), url='http://127.0.0.1:8080/rarecyte/1.0/jobs/slide1@20210422_203831_955885')

我在下面给出的文档中找到了 ANY,但无法弄清楚为什么 assert_called_once_with() 期望调用的实际参数。 这是文档中的相关部分:https://docs.python.org/3/library/unittest.mock.html#any

编辑: make_patch_call() 最终会在计算完补丁函数所需的所有参数后调用这个补丁函数。

def patch(self, url, payload, callback=None, async_run=False, **kwargs):
    payload = self._serialize_payload(payload)
    func = self._do_async_request if async_run else self._do_request
    return func('patch', (url, payload), callback, kwargs)

【问题讨论】:

  • 如果调用匹配,它应该可以工作。你能显示你的实际通话吗(例如 make_patch_call 实际做了什么)?
  • 当然,我已经添加了所谓的补丁函数
  • 问题似乎是kwargs 参数,在调用中是参数svc_auth。这不起作用 - 参数必须匹配(例如,如果您将 kwargs 替换为 svc_auth,它可能会起作用)。我理解意图,但我认为不可能以这种方式匹配argskwargs
  • 太好了,指定 kwargs 的值起作用了!如果你写了这个问题的官方答案,我会选择它作为最佳答案。

标签: python mocking python-unittest


【解决方案1】:

对于assert_called_with,参数和使用的关键字必须完全匹配。将参数替换为ANY 将始终与参数值匹配,但关键字仍必须与使用的关键字匹配。通用关键字 argskwargs 也不例外:如果您期望它们,则必须在调用中使用它们才能匹配。

在这种情况下,预期调用中的 kwargs 关键字:

mock_patch.assert_called_with(url=ANY, payload=ANY, callback=ANY, async_run=ANY, kwargs=ANY)

必须改为真正使用的关键字svc_auth

mock_patch.assert_called_with(url=ANY, payload=ANY, callback=ANY, async_run=ANY, svc_auth=ANY)

请注意,这同样适用于关键字与位置参数,这是一个常见的陷阱。如果您有一个函数foo(bar),那么您必须完全按照调用的方式进行调用,例如:

@mock.patch("my_module.foo")
def test_foo(patched):
    foo(42)
    patched.assert_called_with(ANY)  # passes
    patched.assert_called_with(foo=ANY)  # fails

    foo(bar=42)
    patched.assert_called_with(ANY)  # fails
    patched.assert_called_with(foo=ANY)  # passes

【讨论】:

    猜你喜欢
    • 2018-09-11
    • 1970-01-01
    • 2019-08-08
    • 2015-06-12
    • 1970-01-01
    • 2021-08-18
    • 1970-01-01
    • 2021-03-30
    相关资源
    最近更新 更多