Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/323.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Python数据类中模拟UUID_Python_Mocking_Python Dataclasses - Fatal编程技术网

在Python数据类中模拟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"]

我有这样的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
当我调用
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):
   ...
如果工厂通常不执行复杂的逻辑,这对我来说似乎有点过分了。如果是这样的话,你也可以考虑创建一个普通类而不是一个数据类。