返回可迭代的模拟Python

25 投票
2 回答
43109 浏览
提问于 2025-04-16 19:38

我正在尝试使用Mock来模拟Python中的一个函数。以下是我的代码:

    resp, content = request(...)

这个request()函数需要返回两个值。我尝试了以下方法:

    with patch("syncdatetime.py") as sync_mock:
        sync_mock.request.return_value = [obj, '']

但是当我运行测试时,出现了“Mock对象不可迭代”的错误。这个request函数返回的是一个Mock类型的对象,而不是一个列表。我该如何修改request函数,让它返回一个列表呢?

2 个回答

20

我怀疑你的问题在于,你并没有使用你认为的那个mock实例。默认情况下,调用一个Mock实例会返回另一个Mock。

>>> m = mock.Mock()
>>> type(m())
<class 'mock.mock.Mock'>    

看起来你调用的request返回了一个Mock,因为return_value没有被初始化,这意味着resp, content = request()在尝试解包一个Mock对象。

>>> m = mock.Mock()
>>> (a, b) = m()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'Mock' object is not iterable

你不需要使用side_effect来返回一个列表。直接给return_value赋值就可以了。

>>> m = mock.Mock()
>>> m.return_value = ['a', 'b']
>>> (a, b) = m()
>>> a
'a'
>>> b
'b'
13

我想说明一下,我对mock还不太熟悉,所以不是专家。不过,我刚遇到过同样的问题,发现把side_effect属性设置为一个返回数组的函数可以解决这个问题。

根据你的示例代码,把:

with patch("syncdatetime.py") as sync_mock:
    sync_mock.request.return_value = [obj, '']

改成:

with patch("syncdatetime.py") as sync_mock:
    sync_mock.request.side_effect = function_returning_list

然后定义:

def function_returning_list(arg_list_of_choice):
    #anything you want to do goes here
    #then
    return your_list

撰写回答