在 Python 3.8 中使用 Pydantic v2 给出此示例:
from pydantic import BaseModel
import pytest
from unittest.mock import MagicMock
class MyClass(BaseModel):
a: str = '123'
@pytest.fixture(name='myclass')
def fixture_myclass():
yield MagicMock(wraps=MyClass(), spec=MyClass)
def test_myclass_wraps(myclass):
assert myclass.a == '123'
运行此命令会引发:
AttributeError: Mock object has no attribute 'a'
我希望属性访问能够通过这里的包装器。但是,由于 Pydantic 不正常存储属性和方法,因此
a
不存在于 dir
或 myclass.__dict__
中。我认为这就是为什么 spec
没有按照我期望的方式工作,因为 MagicMock
在底层使用 dir
来检查对象的属性。因此,由于 Pydantic 存储内容的方式,它无法正确指定实例。
那么我如何模拟
BaseModel
类呢?我想使用 spec
来保证测试安全,并使用 wraps
来简化手动模拟量。
为什么不直接创建模型而不是模拟?
import pytest
from pydantic import BaseModel
class MyClass(BaseModel):
a: str = '123'
@pytest.fixture(name='myclass')
def fixture_myclass():
yield MyClass()
def test_myclass_wraps(myclass):
assert myclass.a == '123'
如果您需要配置工厂以供动态使用,那么我推荐polyfactory
from pydantic import BaseModel
from polyfactory.factories.pydantic_factory import ModelFactory
class Person(BaseModel):
name: str
age: float
height: float
weight: float
class PersonFactory(ModelFactory[Person]): ...
def test_is_person() -> None:
person_instance = PersonFactory.build()
assert isinstance(person_instance, Person)
assert isinstance(person_instance.name, str)
assert isinstance(person_instance.age, float)
assert isinstance(person_instance.height, float)
assert isinstance(person_instance.weight, float)