Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to mock in python and still allow the actual code of mocked function to execute

I have recently started using the mock framework in python. It seems that if I patch a function, the actual code is not called - which means that the database changes etc that this actual function does is not implemented. I have been trying to go around it by calling the function before hand and storing the return value and passing it as arg in patch(), but is there a better way to do it? Ideally, I would want a code that works as a silent observer and i can simply ask it if a certain observed function was called or not, how many times, and with what arguments

My current code

return_val = funct()

# C: Now call me again and assert that these intensive computation functions are not called but taken from cache
with patch('funct', return_value=return_val) as mock_task:

    me_response = self.client.get(me_url, format='json')    #should fetch from cache
    assert not mock_task.called
like image 548
dowjones123 Avatar asked Apr 19 '16 11:04

dowjones123


People also ask

How do you mock a function in Python?

How do we mock in Python? Mocking in Python is done by using patch to hijack an API function or object creation call. When patch intercepts a call, it returns a MagicMock object by default. By setting properties on the MagicMock object, you can mock the API call to return any value you want or raise an Exception .

What is the difference between mock and MagicMock?

So what is the difference between them? MagicMock is a subclass of Mock . It contains all magic methods pre-created and ready to use (e.g. __str__ , __len__ , etc.). Therefore, you should use MagicMock when you need magic methods, and Mock if you don't need them.

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.


1 Answers

To mock a method called, you should use the wraps keyword. Consider the following:

class Foo(object):

    def do_thing(self, a):
        print("A: %s" % a)
        self._do_private_thing(a)

    def _do_private_thing(self, a):
        print("PRIVATE STUFF HAPPENING.")
        print("A: %s" % a)

Then In your test you would have something like:

import mock
a = Foo()
with mock.patch.object(a, '_do_private_thing', wraps=a._do_private_thing) as private_mock:
    a.do_thing("lol")
    private_mock.assert_called_with("lol")

Hope this helps.

like image 130
loganasherjones Avatar answered Oct 02 '22 14:10

loganasherjones