繁体   English   中英

如何从模拟对象的方法调用中获取参数?

[英]How to get the arguments from a method call on a mocked object?

我有一个单元测试,其中设置模拟客户端,如下所示:

def setUp(self):
  self.mock_client = mock.patch.object(module_name, 'ClientClassName', autospec=True).start()

然后在我的测试中我有一个伪造的返回值:

def myTest(self):
  self.mock_client.my_method.return_value = ...

现在我想获取调用my_method的参数,但是我一直在努力访问它们。 看来我不能这样做:

mock_args, mock_kwargs = self.mock_client.my_method.call_args

这让我回来了 首先为什么这不起作用? 我确实取得了一点进展,发现:

self.mock_client.method_calls[0]

会给我一个看起来像call().my_method(...the arguments)的调用对象,但我已经尝试了几个小时来访问各个参数,但似乎无法做到。 我哪里错了?

调用参数只是通过订阅mock.call对象来访问,即__getitem__

>>> from unittest.mock import MagicMock 
>>> m = MagicMock() 
>>> m(123, xyz="hello") 
<MagicMock name='mock()' id='140736989479888'>
>>> m("another call")   
<MagicMock name='mock()' id='140736989479888'>
>>> m.call_args_list
[call(123, xyz='hello'), call('another call')]
>>> m.call_args_list[0][0]  
(123,)
>>> m.call_args_list[0][1]  
{'xyz': 'hello'}

第 0 项将是 args 的元组,第 1 项将是 kwargs 的字典。 属性访问也可以工作,例如命名元组(第 0 项是属性“args”,第 1 项是属性“kwargs”)。 如果您只需要访问最近的通话,则可以使用call_args而不是call_args_list

请注意,通常不需要直接访问调用 args,您可以在测试中对另一个调用实例使用断言:

>>> from unittest.mock import call  
>>> m(k=123)
<MagicMock name='mock()' id='140736989479888'>
>>> assert m.call_args == call(k=123)  # pass
>>> assert m.call_args == call(k=124)  # fail
AssertionError

或者更高级别,您可以直接在 mock 上使用m.assert_has_calls

模拟方法时,模拟调用是否有self会受到 autospec 的影响:

>>> from unittest import mock
>>> class A(object):
...     def f(self, *args, **kwargs):
...         pass
... 
>>> with mock.patch("__main__.A.f") as m:
...     a = A()
...     a.f('without autospec', n=1)
... 
>>> m.call_args
call('without autospec', n=1)
>>> with mock.patch("__main__.A.f", autospec=True) as m:
...     a = A()
...     a.f('with autospec', n=2)
... 
>>> m.call_args
call(<__main__.A object at 0x7fffe3d4e6a0>, 'with autospec', n=2)

这在此处的文档中有更详细的讨论。

除了 wim 的答案,您实际上可以深入挖掘这个参数,尽管有时您似乎找到了一个字符串而不是一个真实的对象。

要理解的要点是,当您遍历my_mock.call_args_list时,您会得到unittest.mock._Call类型的对象。 这些确实可以与您自己创建的call(...)对象进行比较。 但这还不是全部。

unittest.mock._Call本身是可迭代的,由 2 个元素组成:一个是另一个list ,另一个是dict 这些就是传递给模拟方法的*args**kwargs

您可以通过调用模拟对象上的 call_args_list 属性来获取参数

暂无
暂无

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

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