如何在测试用例中模拟uuid生成?

时间:2017-06-06 16:56:41

标签: python iterator mocking python-unittest

我有一个测试用例,其中在setUp中,我创建了一个对象,我想在模块uuid4中模拟函数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

我现在的问题是,当我运行写两个测试用例时,第二次创建对象时,它会第一次获得其他uuids。因此,结果取决于我的测试类中的测试用例的数量以及它们的运行顺序,这是我不想要的。

  • 这是模拟uuid发电机的最佳方法吗?
  • 如何在每次调用setUp(或tearDown)时重置或重新创建迭代器?

2 个答案:

答案 0 :(得分:3)

答案比我想象的要容易:只是不要使用迭代器!相反,将uuids列表设置为模拟的side_effect

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

修改

我找到了一种更好的方法将其写为上下文管理器,它允许根据上下文为uuids添加前缀。

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

说明:我正在使用uuid.uuid4模拟函数patch.object(uuid, 'uuid4')。在其中,我将副作用定义为列表。如果你的副作用是一个列表,它可以看作是后续调用中该函数的返回值列表,所以第一次调用函数uuid4()时,它返回该列表的第一个元素,第二个时间第二个元素等。如果在with-context中我生成了10个对象A,则UUID将为'obj_a_uuid_0',最多为'obj_a_uuid_9'

答案 1 :(得分:1)

我找到了一个更好的解决方案:

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

这样,它是通用的,并且适用于所有边缘情况。