Python 模拟多个返回值
我正在使用Python的mock.patch,想要为每次调用改变返回值。这里有个问题:被修改的函数没有输入,所以我不能根据输入来改变返回值。
这是我的代码供参考。
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”。所以我最终是想模拟用户的输入。我尝试过用一个列表来设置返回值,但似乎不太管用。
你可以看到,如果返回值是无效的,我会在这里陷入无限循环。所以我需要一种方法来最终改变返回值,以便我的测试能够顺利结束。
(回答这个问题的另一种可能方式是解释如何在单元测试中模拟用户输入)
这不是这个问题的重复,主要是因为我无法改变输入。
在这个问题的回答中有一个评论提到类似的内容,但没有提供答案或评论。
4 个回答
-9
你还可以使用patch来处理多个返回值:
@patch('Function_to_be_patched', return_value=['a', 'b', 'c'])
记住,如果你对一个方法使用了多个patch,那么它们的顺序会是这样的:
@patch('a')
@patch('b')
def test(mock_b, mock_a);
pass
如你所见,顺序会被反转。最先提到的patch会放在最后的位置。
0
我觉得最简单的解决办法是结合使用 iter()
、patch()
和 side_effect
这几个东西。
from unittest.mock import patch
from return_inputs import *
def test_something_that_has_2_inputs(self):
input_list = ['Foo', 'Bar']
inputs = iter(input_list)
with patch("builtins.input", side_effect=inputs):
name1, name2 = return_inputs()
assert name1 == "Foo"
assert name2 == 'Bar'
17
对于多个返回值,我们可以在初始化补丁时使用side_effect,并将可迭代对象传递给它。
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