python - 检查是否使用不同参数多次调用函数

标签 python unit-testing testing mocking

假设我们有一个函数 f(x,y) 和另一个函数

def g():
       # ...
       f(i,j) # i,j vary and f is called multiple times
       # ...

我们想编写一个单元测试来检查 f 被调用的次数和参数是否正确。

def test_g():
      with patch('mymodule.f') as function:
          assert function.gacs.call_count == correct_no_calls

function.assert_called_with(...)

但这只是指最后一次调用。所以假设 g 调用 f(1,2) 然后调用 f(2,3)function.assert_called_with(1,2 )False

还有

function.call_args_list

它会生成一个包含正确参数的 call 对象列表。将此列表与我们在单元测试中创建的 call 对象进行比较感觉是一件非常讨厌的事情。 call 看起来像是模拟库的内部类。

有更好的方法吗?我使用此设置来测试 apply 函数的并行执行。

最佳答案

即使是@MartinPieters 的回答也是正确的,我认为这不是最好的方法。模拟提供assert_has_calls履行这种职责。

您的测试可能是:

function.assert_has_calls([mock.call(1, 2), mock.call(2, 3)])

在哪里mock.call是一个帮助类来完成这些工作。

请注意,这是一个调用,意味着调用列表应该在调用列表中并且不相等。为了解决这个问题,我通常定义自己的助手 assert_is_calls() 如下

def assert_is_calls(m, calls, any_order=False):
   assert len(m.mock_calls) == len(calls)
   m.assert_has_calls(calls, any_order=any_order)

简历范例

>>> import mock
>>> f = mock.Mock()
>>> f(1)
<Mock name='mock()' id='139836302999952'>
>>> f(2)
<Mock name='mock()' id='139836302999952'>
>>> f.assert_has_calls([mock.call(1), mock.call(2)])
>>> f.assert_has_calls([mock.call(2), mock.call(1)])
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/damico/.local/lib/python2.7/site-packages/mock/mock.py", line 969, in assert_has_calls
    ), cause)
  File "/home/damico/.local/lib/python2.7/site-packages/six.py", line 718, in raise_from
    raise value
AssertionError: Calls not found.
Expected: [call(2), call(1)]
Actual: [call(1), call(2)]
>>> f.assert_has_calls([mock.call(2), mock.call(1)], any_order=True)
>>> f(3)
<Mock name='mock()' id='139836302999952'>
>>> f.assert_has_calls([mock.call(2), mock.call(1)], any_order=True)
>>> f.assert_has_calls([mock.call(1), mock.call(2)])
>>> assert len(f.mock_calls)==2
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AssertionError
>>> assert len(f.mock_calls)==3
>>> def assert_is_calls(m, calls, any_order=False):
...    assert len(m.mock_calls) == len(calls)
...    m.assert_has_calls(calls, any_order=any_order)
... 
>>> assert_is_calls(f, [mock.call(1), mock.call(2), mock.call(3)])
>>> assert_is_calls(f, [mock.call(1), mock.call(3), mock.call(2)])
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 3, in assert_is_calls
  File "/home/damico/.local/lib/python2.7/site-packages/mock/mock.py", line 969, in assert_has_calls
    ), cause)
  File "/home/damico/.local/lib/python2.7/site-packages/six.py", line 718, in raise_from
    raise value
AssertionError: Calls not found.
Expected: [call(1), call(3), call(2)]
Actual: [call(1), call(2), call(3)]
>>> assert_is_calls(f, [mock.call(1), mock.call(3), mock.call(2)], True)
>>> assert_is_calls(f, [mock.call(1), mock.call(3)], True)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 2, in assert_is_calls
AssertionError
>>> 

关于python - 检查是否使用不同参数多次调用函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34225688/

相关文章:

python - 依赖文档字符串的脚本?

由于 tclError,使用 tkinter 的 python 程序无法运行

python - 用 with 语句关闭后重新打开 sys.stdout

python,插入同一行两次时测试不会失败

java - 我应该测试 Spring Boot Application 的 main() 方法吗?如何测试?

python - 如何从多个进程中增加共享计数器?

unit-testing - 与测试驱动开发相比,为什么按契约(Contract)设计不那么流行?

java - @IfProfileValue 两个 Spring 轮廓

testing - Geb:为每个测试打开新标签

testing - 在 Web 应用程序中创建测试数据?