模拟对象库 ANY 没有按预期工作

mock object library ANY not working as expected

我目前正在尝试模拟对服务器的补丁请求,并且我正在尝试使用模拟对象库中的 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)

对于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