Description

When writing unit tests, verifying objects that have unique identifiers generated by uuid.uuid4() can be tricky. By their nature, these UUIDs are random, which makes it impossible to write assertions against specific expected values.

A robust solution is to mock the uuid.uuid4() function to return a predictable, deterministic sequence of values. The unittest.mock.patch function is the perfect tool for this. Its powerful side_effect argument can accept any iterable, including a Python generator.

Example

import unittest  
from unittest.mock import Mock, patch  
import uuid  
  
def uuid_generator():  
    counter = 0  
    while True:  
        yield Mock(hex=f'test_uuid_{counter}')  
        counter += 1  
  
class Unittests(unittest.TestCase):  
    def setUp(self) -> None:  
        self.mock_uuids = uuid_generator()  
  
    def test_context_manager(self):  
        with patch(target="uuid.uuid4", side_effect=self.mock_uuids):  
            self.assertEqual(uuid.uuid4().hex, 'test_uuid_0')  
            self.assertEqual(uuid.uuid4().hex, 'test_uuid_1')  
            self.assertEqual(uuid.uuid4().hex, 'test_uuid_2')  
  
        # be careful: with the self attribute,  
	    # the generator is reset only at the end of the test function
	    with patch(target="uuid.uuid4", side_effect=self.mock_uuids):  
            self.assertEqual(uuid.uuid4().hex, 'test_uuid_3')  
              
        # but with a side_effect calling directly the generator,  
        # the generator is reset at the end of the context manager
        with patch(target="uuid.uuid4", side_effect=uuid_generator()):  
            self.assertEqual(uuid.uuid4().hex, 'test_uuid_0')  
            self.assertEqual(uuid.uuid4().hex, 'test_uuid_1')  
            self.assertEqual(uuid.uuid4().hex, 'test_uuid_2')  
  
        with patch(target="uuid.uuid4", side_effect=uuid_generator()):  
            self.assertEqual(uuid.uuid4().hex, 'test_uuid_0')  
  
    # this is equivalent to using the context manager with the self attribute  
    @patch(target="uuid.uuid4", side_effect=uuid_generator())  
    def test_decorator(self, _):  
        self.assertEqual(uuid.uuid4().hex, 'test_uuid_0')  
        self.assertEqual(uuid.uuid4().hex, 'test_uuid_1')  
        self.assertEqual(uuid.uuid4().hex, 'test_uuid_2')