我正在尝试使用 backport 包将我们的命名元组类移植到 Python 3.6 中的数据类中。但是,我注意到在模拟数据类时,您不能再使用“spec”关键字。我认为这是因为数据类代码是自动生成的。
from dataclasses import dataclass
import mock
@dataclass
class A:
aaa: str
bbb: int
m = mock.Mock(spec=A)
m.aaa
这是我得到的错误:
AttributeError: Mock object has no attribute 'aaa'
知道是否有任何方法可以自动将原始对象的所有属性设置为模拟对象?我有很多包含大量数据的数据类。如果我尝试手动一一设置这些值,那将是非常乏味的。
我最终使用这个通用辅助函数来实现规范对常规类的作用:
import mock
from dataclasses import fields
def create_dataclass_mock(obj):
return mock.Mock(spec=[field.name for field in fields(obj)])
您还可以将具有虚拟值的实例传递给
spec
from unittest.mock import Mock
from dataclasses import dataclass
@dataclass
class A:
aaa: str
bbb: int
m = Mock(spec=A(None, None))
print(m.bbb)
# <Mock name='mock.bbb' id='139766470904856'>
基于mohi666的回答。如果您还想防止设置数据类中未指定的 Mock 属性,请使用
spec_set
而不是 spec
:
import mock
from dataclasses import dataclass, fields
@dataclass
class A:
x: str
def create_dataclass_mock(obj):
return mock.Mock(spec_set=[field.name for field in fields(obj)])
m = create_dataclass_mock(A)
m.x = 'test' # works
m.y = 'another test' # raises AttributeError
数据类字段实际上是作为实例变量实现的。您有 4 个选择:
@dataclass()
class MyDataClass1:
my_field: str = field(default="my_field_val")
m = Mock(spec=MyDataClass1("my_field_val"))
print(m.my_field)
@dataclass()
class MyDataClass2:
my_field: str = field()
m = Mock(spec=MyDataClass2("my_field_val"))
print(m.my_field)
@dataclass()
class MyDataClass3:
my_field: str = field()
m = Mock(spec=MyDataClass3)
m_inst = m()
print(m_inst.my_field)
@dataclass()
class MyDataClass4:
my_field: str = field()
m = Mock(spec_set=[field.name for field in fields(MyDataClass4)])
print(m.my_field)