添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
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')

My Test code:

@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)

替换代码2】只是一个独立于平台(Python 2和3)的 "输入 "版本。所以最终我试图模拟出用户的输入。我试着用一个列表作为返回值,但这似乎并不奏效。

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

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

不是杜撰的this question主要是因为我没有能力改变输入。

答复的意见之一是this question是沿着同样的思路,但没有提供答案/评论。

3 个评论
response is not 'y' or 'n' or 'yes' or 'no' in not做你认为它所做的事。见我如何对一个变量进行多值测试?而你应该not使用is来比较字符串值,使用==来比较价值, not object identities.
这里也要注意。 你似乎想用is来比较字符串字头。 请不要这样做。 事实上,它的作用(有时)只是CPython中的一个实现细节。 另外,response is not 'y' or 'n' or 'yes' or 'no'可能并没有做你认为的那样......
You can use @patch('foo.bar', side_effect=['ret1', ret2', 'ret3']).
python
unit-testing
mocking
python-mock
Nick Humrich
Nick Humrich
发布于 2014-07-23
3 个回答
Martijn Pieters
Martijn Pieters
发布于 2021-03-29
已采纳
0 人赞同

你可以指定一个可迭代的side_effect,并且每次调用mock都会返回序列中的下一个值。

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

Quoting the Mock() documentation:

If side_effect is an 可迭代的 then each call to the mock will return the next value from the 可迭代的.

是否有办法用标准的mock来做这个?是否有办法像我用标准mock那样用MagicMock的补丁?
@Humdinger:这是标准的Mock类的一个特征。
指派一个列表似乎只在python 3下工作。用python 2.7测试,我需要用一个迭代器来代替(m.side_effect = iter(['foo', 'bar', 'baz']))。
@user686249:我确实可以重现这一点,因为从方法中推测会产生一个lambda(一个函数),而不是一个MagicMock。一个函数对象不能属性,所以side_effect属性是一个可迭代函数。不过你不应该这样规范这个方法。最好使用mock.patch.object(requests.Session, 'post')导致一个修补器对象正确地自动规范该方法。 supports side_effect properly.
@JoeMjr2:当迭代器被耗尽时,StopIteration被提出。 你可以使用任何迭代器,所以你可以使用itertools.chain(['Foo'], itertools.repeat('Bar'))来产生Foo一次,然后永远产生Bar
shrhawk
shrhawk
发布于 2021-03-29
0 人赞同

对于多个返回值,我们可以使用side_effect在补丁初始化过程中也是如此,并把可迭代的东西传给它

sample.py

def hello_world():

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
    
avinash bhat
avinash bhat
发布于 2021-03-29
0 人赞同

你也可以对多个返回值使用补丁。

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

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

@patch('a')