在Python数据类中模拟UUID
我有这样的UUID数据类:在Python数据类中模拟UUID,python,mocking,python-dataclasses,Python,Mocking,Python Dataclasses,我有这样的UUID数据类: import uuid from dataclasses import dataclass, field from typing import Union @dataclass class Foo: id: Union[uuid.UUID, None] = field(default_factory=uuid.uuid4) from unittest.mock import patch TEST_UUIDS = ["uuid1", "uuid2"]
import uuid
from dataclasses import dataclass, field
from typing import Union
@dataclass
class Foo:
id: Union[uuid.UUID, None] = field(default_factory=uuid.uuid4)
from unittest.mock import patch
TEST_UUIDS = ["uuid1", "uuid2"]
with patch.object(uuid, "uuid4", side_effects=TEST_UUIDS):
print(uuid.uuid4()) # Output: uuid1
print(Foo().id) # Output: an actual UUID
当我调用Foo()
时,它会创建一个具有生成的UUID的对象
现在我想在测试中模拟这个UUID工厂,如下所示:
import uuid
from dataclasses import dataclass, field
from typing import Union
@dataclass
class Foo:
id: Union[uuid.UUID, None] = field(default_factory=uuid.uuid4)
from unittest.mock import patch
TEST_UUIDS = ["uuid1", "uuid2"]
with patch.object(uuid, "uuid4", side_effects=TEST_UUIDS):
print(uuid.uuid4()) # Output: uuid1
print(Foo().id) # Output: an actual UUID
我的预期输出是
uuid2
。所以问题是:我如何正确地修补工厂?在文档或此处找不到任何内容…TL;DR最好只做打印(Foo(id=“uuid1”).id)
解释
以下是不起作用的地方:(除了副作用的打字错误)
产出:
140470453723216
140470456506848
这是因为,补丁程序没有更改实际的uuid.uuid4
函数,而是创建了一个新的函数,覆盖了命名空间中的正常uuid.uuid4
,如id中的更改所示。由于工厂已经初始化,此更改没有任何效果,除非在with
块中创建类,否则这对于实际测试是不切实际的
但即使这样做了,也不会有什么不同,因为它会生成\uuuuuu init\uuuuu
函数,并一次创建对默认工厂的引用,而不是为每个\uuuuuu init\uuu
调用创建引用。因此,以下各项也不起作用:
您可以做的是重写\uuuuu init\uuuu
函数:
from copy import copy
# Copy is required to avoid recursion after rewrite
foo_init_copy = copy(Foo.__init__)
def mock_init(foo):
foo_init_copy(foo)
foo.id = "x"
with patch.object(Foo, "__init__", new=mock_init):
...
如果工厂通常不执行复杂的逻辑,这对我来说似乎有点过分了。如果是这样的话,你也可以考虑创建一个普通类而不是一个数据类。