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.
Here is my code for reference.
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)
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.
response is not 'y' or 'n' or 'yes' or 'no'
in not doing what you think it does. See How do I test one variable against multiple values? and you should not useis
to compare string values, use==
to compare values, not object identities. – Martijn Pieters♦is
to compare string literals. Don't do that. The fact that it works (sometimes) is only an implementation detail in CPython. Also,response is not 'y' or 'n' or 'yes' or 'no'
probably isn't doing what you think it is... – mgilson@patch('foo.bar', side_effect=['ret1', ret2', 'ret3'])
. – Acumenus