## A very short introduction to the mock library¶

Mock objects are useful in unit testing as stand ins for other objects or functions. You might use a mock object instead of the real thing when: the real thing is expensive to create, the real thing requires online resources that might be offline, or you just want to do really fine grained testing. With mock objects you can easily control what they do and then test whether they were used as intended.

There are a number of Python mock libraries but the one discussed here is mock: http://www.voidspace.org.uk/python/mock/.

In [1]:
import mock


### Mock a function¶

Here I use a mock object to stand in for a function. No matter how it is called it will return 42.

In [2]:
mock_func = mock.Mock()
mock_func.return_value = 42
print mock_func(6, 9)

42


Mock objects remember how they have been called and you can test that they were called correctly.

In [3]:
mock_func.assert_called_with(6, 9)


If the calling sequences don't match you get an assertion error.

In [4]:
mock_func.assert_called_with(6, 7)

---------------------------------------------------------------------------
AssertionError                            Traceback (most recent call last)
<ipython-input-4-c5e431097d00> in <module>()
----> 1 mock_func.assert_called_with(6, 7)

/Users/mrdavis/py-lib/mock-1.0b1-py2.7.egg/mock.pyc in assert_called_with(_mock_self, *args, **kwargs)
822         if self.call_args != (args, kwargs):
823             msg = self._format_mock_failure_message(args, kwargs)
--> 824             raise AssertionError(msg)
825
826

AssertionError: Expected call: mock(6, 7)
Actual call: mock(6, 9)

assert_called_with applies only to the most recent call.

### Mock a non-callable class¶

Here I use a mock object to stand in for a class and method. It looks very similar to above. A NonCallableMock is basically the same as a plain Mock except it cannot be called.

In [5]:
mock_class = mock.NonCallableMock()
mock_class.some_method.return_value = 42
print mock_class.some_method(6, 9)

42

In [6]:
mock_class.some_method.assert_called_once_with(6, 9)


### Side effects¶

Mock objects can have side effects when called instead of simple return values. One desireable side effect might be to raise an exception to make sure your code under test responds correctly.

In [7]:
mock_func_w_side_effect = mock.Mock()
mock_func_w_side_effect.side_effect = ValueError('Wrong!')
mock_func_w_side_effect()

---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
1 mock_func_w_side_effect = mock.Mock()
2 mock_func_w_side_effect.side_effect = ValueError('Wrong!')
----> 3 mock_func_w_side_effect()

/Users/mrdavis/py-lib/mock-1.0b1-py2.7.egg/mock.pyc in __call__(_mock_self, *args, **kwargs)
942         # in the signature
943         _mock_self._mock_check_sig(*args, **kwargs)
--> 944         return _mock_self._mock_call(*args, **kwargs)
945
946

/Users/mrdavis/py-lib/mock-1.0b1-py2.7.egg/mock.pyc in _mock_call(_mock_self, *args, **kwargs)
997         if effect is not None:
998             if _is_exception(effect):
--> 999                 raise effect
1000
1001             if not _callable(effect):

ValueError: Wrong!

Another side effect is a function that actually does something, but I couldn't think of many uses for this.

In [8]:
mock_func_w_side_effect.side_effect = lambda x, y: x + y
mock_func_w_side_effect('spam', 'SPAM')

Out[8]:
'spamSPAM'

### Patching¶

Creating mock objects directly as in the above examples can be useful for constructing objects passed to code under test but you may also want to replace functions and objects used by the code under test. Since you don't have direct access to these you can use mock's patch utility, which comes in several flavors.

As an example I'll create a toy function to test. It simply calls json.dumps. (Read more about the json module here: http://docs.python.org/library/json.html.)

In [9]:
import json
def func_with_json(d):
return json.dumps(d)

In [10]:
d = {'a': 1, 'b': [2, 3]}  # a simple input for func_with_json


mock.patch can be used as a context manager. Here it replaces the function json.dumps. At the end of the code block within the context manager json.dumps goes back to its normal state.

In [11]:
with mock.patch('json.dumps') as mock_dumps:
mock_dumps.return_value = 'JSON'
r = func_with_json(d)
assert r == 'JSON'
mock_dumps.assert_called_once_with(d)


Outside the context block json.dumps works as normal:

In [12]:
print json.dumps(d)

{"a": 1, "b": [2, 3]}


mock.patch can also be used as a function or class decorator, replacing an object inside the function or class.

Here we use mock.patch to replace json.dumps within a test function. The mock object replacing json.dumps is passed to the test function as an argument.

In [13]:
@mock.patch('json.dumps')
def test_func_with_json(mock_dumps):
mock_dumps.return_value = 'JSON'
r = func_with_json({'c': {'d': [4]}})
assert r == 'JSON'
mock_dumps.assert_called_once_with(d)  # whoops, we didn't pass in d, this should fail.
test_func_with_json()

---------------------------------------------------------------------------
AssertionError                            Traceback (most recent call last)
<ipython-input-13-0c4563c6a92d> in <module>()
5     assert r == 'JSON'
6     mock_dumps.assert_called_once_with(d)  # whoops, we didn't pass in d, this should fail.
----> 7 test_func_with_json()

/Users/mrdavis/py-lib/mock-1.0b1-py2.7.egg/mock.pyc in patched(*args, **keywargs)
1188
1189                     args += tuple(extra_args)
-> 1190                     return func(*args, **keywargs)
1191                 except:
1192                     if (patching not in entered_patchers and

<ipython-input-13-0c4563c6a92d> in test_func_with_json(mock_dumps)
4     r = func_with_json({'c': {'d': [4]}})
5     assert r == 'JSON'
----> 6     mock_dumps.assert_called_once_with(d)  # whoops, we didn't pass in d, this should fail.
7 test_func_with_json()

/Users/mrdavis/py-lib/mock-1.0b1-py2.7.egg/mock.pyc in assert_called_once_with(_mock_self, *args, **kwargs)
833                    self.call_count)
834             raise AssertionError(msg)
--> 835         return self.assert_called_with(*args, **kwargs)
836
837

/Users/mrdavis/py-lib/mock-1.0b1-py2.7.egg/mock.pyc in assert_called_with(_mock_self, *args, **kwargs)
822         if self.call_args != (args, kwargs):
823             msg = self._format_mock_failure_message(args, kwargs)
--> 824             raise AssertionError(msg)
825
826

AssertionError: Expected call: dumps({'a': 1, 'b': [2, 3]})
Actual call: dumps({'c': {'d': [4]}})

There are a number of different kinds of patches and different ways to use them. For more information refer to the mock documentation.

In [ ]: