如何使用 MagicMock 规范和包装来测试 Pydantic BaseModel

问题描述 投票:0回答:1

在 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
来简化手动模拟量。

python pytest pydantic python-unittest.mock pydantic-v2
1个回答
0
投票

为什么不直接创建模型而不是模拟?

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)
© www.soinside.com 2019 - 2024. All rights reserved.