Mocking UUID.hex

March 20, 2015

Mocking is an indispensable tool when writing unit tests, allowing you to temporarily replace parts of your system under test with controlled, predictable mock objects. I recently struggled to mock UUID.hex, a read-only attribute on instances of the UUID class. Ned Batchelder has written about mocking datetime.today(). This is a good resource if you’re trying to mock out a method belonging to a class from a module imported by your code under test.

However, my goal was to mock out an object property, specifically a property (hex) on an instance of a class (UUID) belonging to a module (uuid) imported by my code under test. I ended up using the following code in my test class, where target_module represents the module being tested:

def setUp(self):
    uuid_patcher = mock.patch.object(
        target_module.uuid.UUID,
        'hex',
        new_callable=mock.PropertyMock(return_value=self.UUID_HEX)
    )
    mocked_uuid = uuid_patcher.start()
    self.addCleanup(uuid_patcher.stop)

What’s going on here? In a nutshell, patch.object() is used to replace the hex property on instances of target_module.uuid.UUID with a PropertyMock which returns some fixed value, self.UUID_HEX. The rest of the uuid module’s functionality remains intact.

I hit a couple of stumbling blocks while figuring out how to do this. The first was identifying the right target to patch. The module I was trying to test – target_module – imported uuid, requiring me to patch the hex attribute on instances of target_module.uuid.UUID. Patching the hex attribute on uuid.UUID only replaces hex with a mock object within the scope of the test module itself, not the module under test.

The second challenge for me was replacing hex with the right kind of Mock object, that being a PropertyMock. As you might have guessed, this subclass of Mock creates a mock object intended to be used as a property. Getting a PropertyMock instance from an object calls the mock with no arguments and returns whatever return value you’ve specified. The key to replacing hex with a PropertyMock is specifying PropertyMock as a new callable when invoking patch.object(). By default, patch.object() replaces its target attribute with an instance of MagicMock. Specifying PropertyMock as a new callable instructs patch.object() to use this alternative subclass of Mock when patching attributes.