Python模拟多个返回值

我正在使用python mock。补丁,并希望更改每个调用的返回值。 以下是警告: 正在修补的函数没有输入,所以我不能根据输入改变返回值

下面是我的代码供参考。

def get_boolean_response():
response = io.prompt('y/n').lower()
while response not in ('y', 'n', 'yes', 'no'):
io.echo('Not a valid input. Try again'])
response = io.prompt('y/n').lower()


return response in ('y', 'yes')

我的测试代码:

@mock.patch('io')
def test_get_boolean_response(self, mock_io):
#setup
mock_io.prompt.return_value = ['x','y']
result = operations.get_boolean_response()


#test
self.assertTrue(result)
self.assertEqual(mock_io.prompt.call_count, 2)

io.prompt只是一个平台独立(python 2和3)版本的“input”。最终我要模拟出用户的输入。我已经尝试使用一个列表的返回值,但这并不接缝工作。

你可以看到,如果返回值是无效的,我就会得到一个无限循环。所以我需要一种最终改变返回值的方法,这样我的测试才能真正完成。

(回答这个问题的另一种可能的方式是解释我如何在单元测试中模拟用户输入)


不是这个问题的dup,主要是因为我没有改变输入的能力。

这个问题上的Answer的注释之一是沿着相同的路线,但没有提供答案/注释。

211830 次浏览

可以将< em > iterable < / em >赋值给side_effect,并且每次调用mock时,mock都会返回序列中的下一个值:

>>> from unittest.mock import Mock
>>> m = Mock()
>>> m.side_effect = ['foo', 'bar', 'baz']
>>> m()
'foo'
>>> m()
'bar'
>>> m()
'baz'

引用Mock()文档:

如果side_effect是一个可迭代对象,则每次调用mock都将返回该可迭代对象中的下一个值。

你也可以对多个返回值使用patch:

@patch('Function_to_be_patched', return_value=['a', 'b', 'c'])

记住,如果你为一个方法使用了多个补丁,那么它的顺序将是这样的:

@patch('a')
@patch('b')
def test(mock_b, mock_a);
pass

正如你在这里看到的,它将被还原。第一个提到的补丁将在最后一个位置。

对于多个返回值,我们也可以在补丁初始化时使用side_effect,并将iterable传递给它

sample.py

def hello_world():
pass

test_sample.py

from unittest.mock import patch
from sample import hello_world


@patch('sample.hello_world', side_effect=[{'a': 1, 'b': 2}, {'a': 4, 'b': 5}])
def test_first_test(self, hello_world_patched):
assert hello_world() == {'a': 1, 'b': 2}
assert hello_world() == {'a': 4, 'b': 5}
assert hello_world_patched.call_count == 2