Python mock - Check if methods are called in mocked object

Viewed 3956

I have a certain piece of code that looks like this:

# file1.py
from module import Object

def method():
    o = Object("param1")
    o.do_something("param2")

I have unittests that look like this:

@patch("file1.Object")
class TestFile(unittest.TestCase):
    def test_call(self, obj):
        ...

I can do obj.assert_called_with() in the unittest to verify that the constructor was called with certain parameters. Is it possible to verify that obj.do_something was called with certain parameters? My instinct is no, as the Mock is fully encapsulated within Object, but I was hoping there might be some other way.

2 Answers

You can do this, because the arguments are passed to the mock object.
This should work:

@patch("file1.Object")
class TestFile:
    def test_call(self, obj):
        method()
        obj.assert_called_once_with("param1")
        obj.return_value.do_something.assert_called_once_with("param2")

obj.return_value is the Object instance (which is a MagickMock object with the Object spec), and do_something is another mock in that object that is called with the given parameter.

As long as you are just passing arguments to mock objects, the mock will record this and you can check it. What you don't have is any side effects from the real function calls - so if the original do_something would call another function, this cannot be checked.

When you mock an object, it will mock the methods inside the object aswell. Therefore you are able to see if obj.do_something has been called with certain parameters as obj.do_something.assert_called_with()

For more information regarding unittest mocking can be found at the python library wiki https://docs.python.org/3/library/unittest.mock.html

A perfect example of what you are asking exist within that wiki source:

>>> mock = Mock()
>>> mock.method(1, 2, 3, test='wow')
<Mock name='mock.method()' id='...'>
>>> mock.method.assert_called_with(1, 2, 3, test='wow')

https://docs.python.org/3/library/unittest.mock.html#unittest.mock.Mock.assert_called_with

Regards, I see that you placed the the patching on the object, try placing it on the function instead, like:

class TestFile(unittest.TestCase):
    @patch("file1.Object")
    def test_call(self, obj):
        ...
Related