I have a test case in which in the setUp, I create an object for which I want to mock the function uuid4
in the module uuid
.
TEST_UUIDS = ['uuid_{}'.format(i) for i in range(10000)]
UUID_POOL = iter(TEST_UUIDS)
def generate_uuid() -> str:
return next(UUID_POOL)
class MyTestCase(TestCase):
def setUp(self, **kwargs):
self._create_my_object
@patch.object(uuid, 'uuid4', generate_uuid)
def _create_my_object(self):
# Create an object using a uuid
My problem now is that when I run write two test cases, the second time the object is created, it gets other uuids as the first time. Therefore, the result is dependent on the number of test cases in my test class and the order they are run in, something I don't want.
uuid1() function is used to generate a UUID from the host ID, sequence number, and the current time. It uses the MAC address of a host as a source of uniqueness. The node and clock_seq are optional arguments. The node is the hardware address, which is a 48-bit positive integer.
A UUID (Universal Unique Identifier) is a 128-bit value used to uniquely identify an object or entity on the internet. Depending on the specific mechanisms used, a UUID is either guaranteed to be different or is, at least, extremely likely to be different from any other UUID generated until A.D. 3400.
This module provides immutable UUID objects (the UUID class) and the functions uuid1() , uuid3() , uuid4() , uuid5() for generating version 1, 3, 4, and 5 UUIDs as specified in RFC 4122. If all you want is a unique ID, you should probably call uuid1() or uuid4() .
The answer was easier than I thought: just don't use iterators! Instead, set the list of uuids as side_effect
of the mock.
TEST_UUIDS = ['uuid_{}'.format(i) for i in range(10000)]
class MyTestCase(TestCase):
def setUp(self, **kwargs):
self._create_my_object
@patch.object(uuid, 'uuid4', side_effect=TEST_UUIDS)
def _create_my_object(self):
# Create an object using a uuid
EDIT
I found an even nicer way to write this as a context manager, which allows for prefixing uuids based on the context.
TEST_UUIDS = ['uuid_{}'.format(i) for i in range(10000)]
def uuid_prefix(prefix: str):
return patch.object(uuid, 'uuid4', side_effect=['{}_{}'.format(prefix, x) for x in TEST_UUIDS])
class MyTestCase(TestCase):
def setUp(self, **kwargs):
self._create_my_object
def _create_my_object(self):
with uuid_prefix('obj_a'):
# Create an object A using a uuid
with uuid_prefix('obj_b'):
# Create an object B using a uuid
Explanation: I am mocking the function uuid.uuid4
using patch.object(uuid, 'uuid4')
. In it, I define a side effect as a list. If your side effect is a list, it can be seen as a list of return values of that function on subsequent calls, so the first time the function uuid4()
is called, it returns the first element of that list, the second time the second element, etc. If in the with-context I am generating 10 objects A, the UUIDs will be 'obj_a_uuid_0'
up to 'obj_a_uuid_9'
.
I found an even nicer solution:
TEST_UUIDS_COUNT = 0
def mock_uuid():
global TEST_UUIDS_COUNT
TEST_UUIDS_COUNT += 1
return uuid.UUID(int=TEST_UUIDS_COUNT)
class MyTestCase(TestCase):
def setUp(self, **kwargs):
self._create_my_object
@patch('uuid.uuid4', mock_uuid)
def _create_my_object(self):
# Create an object using a uuid
This way it is universal and works with all edge cases.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With