Python模拟多个返回值

我正在使用pythons mock.patch并想要更改每个调用的返回值。 这里是警告:被修补的函数没有input,所以我不能根据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') 

我的testing代码:

 @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”。 所以最终我试图嘲笑用户的input。 我已经尝试使用返回值的列表,但是不缝合工作。

你可以看到,如果返回值是无效的,我会在这里得到一个无限循环。 所以我需要一种方法来最终改变返回值,以便我的testing实际完成。

(另一个可能的方法来回答这个问题可能是解释我怎么可以在unit testing中模仿用户input)


不是这个问题的重复,主要是因为我没有能力改变input。

对这个问题的答复之一是同样的意见,但没有提供答复/评论。

您可以将一个迭代器分配给side_effect ,并且每次调用时side_effect都会返回序列中的下一个值:

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

引用Mock()文档 :

如果side_effect是可迭代的,那么对模拟的每次调用将返回来自迭代器的下一个值。

另外,testingresponse is not 'y' or 'n' or 'yes' or 'no'不起作用。 你在问是否expression式(response is not 'y')是真的,或者'y'是true(总是这样,一个非空string总是true)等等。 独立 。 请参阅如何针对多个值testing一个variables?

你也不应该用来testing一个string。 CPython解释器可能会 在某些情况下重用string对象,但这不是您应该依赖的行为。

因此,使用:

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

代替; 这将使用平等testing( == )来确定response引用具有相同内容(值)的string。

response == 'y' or 'yes' 。 请response in ('y', 'yes')使用response in ('y', 'yes')