Python模拟多个返回值 [英] Python mock multiple return values

查看:305
本文介绍了Python模拟多个返回值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用pythons mock.patch并想更改每个调用的返回值. 注意事项: 修补的函数没有输入,因此我无法根据输入更改返回值.

I am using pythons mock.patch and would like to change the return value for each call. Here is the caveat: the function being patched has no inputs, so I can not change the return value based on the input.

这是我的代码供参考.

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).因此,最终我将尝试模拟用户的输入.我曾尝试使用列表作为返回值,但这并不能正常工作.

io.prompt is just a platform independent (python 2 and 3) version of "input". So ultimately I am trying to mock out the users input. I have tried using a list for the return value, but that doesn't seam to work.

您可以看到,如果返回值无效,那么我将在此处得到一个无限循环.因此,我需要一种最终更改返回值的方法,以便我的测试实际上完成.

You can see that if the return value is something invalid, I will just get an infinite loop here. So I need a way to eventually change the return value, so that my test actually finishes.

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

(another possible way to answer this question could be to explain how I could mimic user input in a unit-test)

不是此问题的重复,主要是因为我没有能力改变输入.

Not a dup of this question mainly because I do not have the ability to vary the inputs.

关于此问题的答案的评论之一大致相同,但未提供答案/评论.

One of the comments of the Answer on this question is along the same lines, but no answer/comment has been provided.

推荐答案

您可以分配

You can assign an iterable to side_effect, and the mock will return the next value in the sequence each time it is called:

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

引用 Mock()文档 :

如果 side_effect 是可迭代的,则每次对模拟的调用都将返回可迭代的下一个值.

If side_effect is an iterable then each call to the mock will return the next value from the iterable.

顺便说一句,测试response is not 'y' or 'n' or 'yes' or 'no'起作用;您在问表达式(response is not 'y')是true,还是'y'是true(总是这样,非空字符串始终是true),等等.or运算符两侧的各种表达式是独立.请参见如何针对多个值测试一个变量?

As an aside, the test response is not 'y' or 'n' or 'yes' or 'no' will not work; you are asking if the expression (response is not 'y') is true, or 'y' is true (always the case, a non-empty string is always true), etc. The various expressions on either side of or operators are independent. See How do I test one variable against multiple values?

您还应该不要使用is对字符串进行测试. CPython解释器可以在某些情况下重用字符串对象 ,但这不是您应该依靠的行为.

You should also not use is to test against a string. The CPython interpreter may reuse string objects under certain circumstances, but this is not behaviour you should count on.

这样,使用:

response not in ('y', 'n', 'yes', 'no')

相反;这将使用 quality 测试(==)确定response是否引用具有相同内容(值)的字符串.

instead; this will use equality tests (==) to determine if response references a string with the same contents (value).

response == 'y' or 'yes'也是如此;使用response in ('y', 'yes')代替.

The same applies to response == 'y' or 'yes'; use response in ('y', 'yes') instead.

这篇关于Python模拟多个返回值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆