Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

python mock side_effect or return_value dependent on call_count

Tags:

python

mocking

To test a polling function I want to mock the calling of a sub function so that the first time it is called it will fail, and the second time it is called it will succeed. Here's a very simplified version of it:

poll_function(var1):     value = sub_function(var1)  # First call will return None     while not value:         time.sleep(POLLING_INTERVAL)           value = sub_function(var1) # A subsequent call will return a string, e.g "data"     return value 

Is this possible to do with a Mock object from the mock framework? I know Mock objects have a call_count attribute I should be able to use somehow.

Right now I've solved it by creating a custom mock object that I use to monkey patch sub_function(), but I feel there should be a better less verbose way of doing it:

def test_poll():     class MyMock(object):                                                                def __init__(self, *args):                                                          self.call_count = 0                                                          def sub_function(self, *args, **kwargs):                                          if self.call_count > 1:                                                             return "data"                         else:                                                                               self.call_count += 1                                                            return None        my_mock = MyMock()                                                              with patch('sub_function', my_mock.sub_function):                    ok_(poll_function())          
like image 636
imolit Avatar asked Nov 13 '12 10:11

imolit


People also ask

What is Side_effect in mock python?

side_effect: A function to be called whenever the Mock is called. See the side_effect attribute. Useful for raising exceptions or dynamically changing return values. The function is called with the same arguments as the mock, and unless it returns DEFAULT , the return value of this function is used as the return value.

What is the difference between mock and MagicMock?

With Mock you can mock magic methods but you have to define them. MagicMock has "default implementations of most of the magic methods.". If you don't need to test any magic methods, Mock is adequate and doesn't bring a lot of extraneous things into your tests.

What is mocking in unit testing Python?

What is mocking in Python? Mocking in Python means the unittest. mock library is being utilized to replace parts of the system with mock objects, allowing easier and more efficient unit testing than would otherwise be possible.

What is mock patch?

mock provides a powerful mechanism for mocking objects, called patch() , which looks up an object in a given module and replaces that object with a Mock . Usually, you use patch() as a decorator or a context manager to provide a scope in which you will mock the target object.


1 Answers

If I understand your question correctly, you do it by setting side_effect to an iterable. For your simple case:

>>> mock_poll = Mock(side_effect=[None, 'data']) >>> mock_poll() None >>> mock_poll() 'data' 

If you want to allow for an unlimited number of calls, use the itertools cycle and chain functions:

>>> mock_poll = Mock(side_effect=chain(['first'], cycle(['others']))) 
like image 164
aquavitae Avatar answered Sep 18 '22 17:09

aquavitae