【问题标题】:python: assert_has_calls taking last value in looppython:assert_has_calls 在循环中取最后一个值
【发布时间】:2021-11-23 03:44:12
【问题描述】:

我有一个类似于foo 的函数,我正在尝试使用以下代码对其进行测试

from unittest.mock import call, patch

def foo():
    x = {}
    for i in range(3):
        x["val"] = i
        print(x)

@patch('builtins.print')
def test_foo(print_mock):
    foo()
    calls = calls = [call({'val': 0}), call({'val': 1}), call({'val': 2})]
    print_mock.assert_has_calls(calls)

test_foo()

但它给出了以下错误

File "/usr/lib/python3.8/unittest/mock.py", line 950, in assert_has_calls
    raise AssertionError(
AssertionError: Calls not found.
Expected: [call({'val': 0}), call({'val': 1}), call({'val': 2})]
Actual: [call({'val': 2}), call({'val': 2}), call({'val': 2})]

我认为问题在于它采用了调用函数的最后一个值。 希望有修复或其他方法来测试foo 函数

更新

python 文档中有一些workaround 用于此问题

【问题讨论】:

  • 这符合预期 - 函数被调用了 3 次 x,其值如测试期间所示。也许您真的想打印ix["val"]
  • @MrBeanBremen 该函数被调用了三次,参数为{val: 0}{val: 1}{val: 2}。但是它期望所有调用都为{val: 2}
  • 对,就是调用后x的值。 mock 记得它被 x 调用了 3 次,它不会复制参数。
  • 好的,那么有没有办法测试这样的功能呢?在foo 中,如果我将print(x) 更新为print(deepcopy(x)),则测试通过。
  • 是的,完全正确。为了做你想做的事,你可以使用 print 的模拟,你自己保存调用参数。

标签: python python-3.x python-unittest python-mock python-unittest.mock


【解决方案1】:

我认为你实现了这种行为?

  1 from unittest.mock import call, patch
  2 
  3 def foo():
  4     x = {}
  5     for key, value in zip(range(3), range(3)):
  6         x[key] = value
  7         print(x)
  8 
  9 @patch("builtins.print")
 10 def test_foo(print_mock):
 11     foo()
 12     calls = [call({0: 0, 1: 1, 2: 2})]
 13     print_mock.assert_has_calls(calls)
 14 
 15 test_foo()

【讨论】:

  • 在我的实际用例中,该函数是一个外部API调用,所以我无法更改字典的键值
猜你喜欢
  • 2019-08-01
  • 2015-04-08
  • 1970-01-01
  • 2019-03-02
  • 2022-01-03
  • 2016-03-03
  • 2021-12-27
  • 2018-01-29
相关资源
最近更新 更多