Mock Python's Builtin Functions
Recently, working on some unit test code, I ran into a situation where I needed to mock out some of Python’s builtin functions. At first I wasn’t even sure if this was possible. Luckily, in Python, the builtin functions aren’t treated or handled differently than any other custom functions you may have defined in your code.
You can mock those functions out the same way that you would with other functions more specific to your code. The only thing that you need to keep in mind is where the builtin functions are coming from and how your code is calling them.
For example, if you had a script named mock_builtin.py with the following code, and you needed to write some unit tests for OjectHasher’s hash_obj function:
class ObjectHasher(object):
def hash_obj(self, obj):
return hash(obj)
If for some reason you could not guarantee consistent output from the hash builtin or having a different hash output is easier to work with in your tests. You may want to mock out that function call. You can easily do that using the mock module.
Here are a few different ways you can use the mock module to manipulate the builtin hash function in the above code.
import mock
import unittest
import mock_builtin
import __builtin__
class ObjectHasherTests(unittest.TestCase):
def test_hash_obj1(self):
"""Using the mock.patch.object context manager"""
with mock.patch.object(__builtin__, 'hash') as mock_hash:
mock_hash.return_value = 'unittest_hash_output'
test_object = mock_builtin.ObjectHasher()
output = test_object.hash_obj('test input')
mock_hash.assert_called_with('test input')
assert(output == 'unittest_hash_output')
@mock.patch.object(__builtin__, 'hash')
def test_hash_obj2(self, mock_hash):
"""Using the mock.patch.object decorator"""
mock_hash.return_value = 'unittest_hash_output'
test_object = mock_builtin.ObjectHasher()
output = test_object.hash_obj('test input')
mock_hash.assert_called_with('test input')
assert(output == 'unittest_hash_output')
@mock.patch('__builtin__.hash')
def test_hash_obj3(self, mock_hash):
"""Using the mock.patch decorator (removes the need to import __builtin__)"""
mock_hash.return_value = 'unittest_hash_output'
test_object = mock_builtin.ObjectHasher()
output = test_object.hash_obj('test input')
mock_hash.assert_called_with('test input')
assert(output == 'unittest_hash_output')
There are probably many other ways to achieve this with mock, I just wanted to highlight the different ways in which I normally do this.
You can apply these techniques to any other Python builtin function (print, range, map, open, …) which is very powerful in certain situations. Usually it is not necessary to mock the builtins but sometimes you need to or want to. Most of the time it’s not the builtin functions that we are testing anyways since we can be confident that those will work as expected. However, the more that you mock, the less “real” the unit test will become, so make sure to keep that in mind while writing your tests.
I should also note that I am using Python 2.7 in the code above. You will need
to run pip install mock
to download the mock module if you don’t already have
it available in your environment. Let me know if you have any comments or
questions below, happy mocking!
11/6/2016