Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get the call count using Mock @patch?

I am writing a unit test for some library we are working on. This library makes use of requests.post() to perform POST HTTP requests to an external server.

Inside my UT, I obviously don't want to contact the real server but to mock the response.

To do that, I wrote a function that goes like:

def mocked_post(url, headers, data, **kwargs):
    response = Mock()

    # Some logic, irrelevant here.

    return response

And I patched this function around my unit test class:

@patch('mylib.requests.post', mocked_post)
class MyTest(TestCase):

    def test_foo(self):
        # Some test logic

This is working perfectly.

Now I'd like to get the number of calls to my mocked function. I tried mocked_post.call_count but that doesn't exist. I tried to find this property on a lot of different objects (including mylib.requests.post) but no luck so far.

How can I access the call_count for this mocked function ?

like image 700
ereOn Avatar asked Feb 24 '14 08:02

ereOn


People also ask

What does mock patch do?

patch() unittest. 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.

What is the difference between mock and MagicMock?

Mock vs. 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.

How do you mock method calls 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 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

I'd not use mocked_post as the new argument here. I'd set up the side_effect attribute of a fresh Mock instead:

@patch('mylib.requests.post') class MyTest(TestCase):      def test_foo(self, post_mock):         post_mock.side_effect = mocked_post          # Some test logic          self.assertEqual(post_mock.call_count, 3) 

Now you have the Mock object that patch generates for you as an argument to all your test methods, and you can thus test how many times that mock was called.

You should be able to set the side_effect attribute in the decorator as well, to apply to all tests:

@patch('mylib.requests.post', side_effect=mocked_post) class MyTest(TestCase):      def test_foo(self, post_mock):         # Some test logic          self.assertEqual(post_mock.call_count, 3) 

You'll still have trouble accessing the returned response object, however; you may want to return mock.DEFAULT from mocked_post instead of creating one in the function, so that you can then use post_mock.return_value to make further assertions on the returned object.

like image 198
Martijn Pieters Avatar answered Sep 27 '22 21:09

Martijn Pieters