【问题标题】:Create MagicMock that acts like a class object and when instantiated creates a MagicMock instance创建类似于类对象的 MagicMock,并在实例化时创建一个 MagicMock 实例
【发布时间】:2020-06-13 15:58:14
【问题描述】:

我有一个相当有趣的问题。我正在尝试模拟一个可以通过内部验证的类,并且在实例化时会返回一个 magicmock 实例。

例如,我有一个 pydantic 模型可以验证以下字段:

from typing import Type
from pydantic import BaseModel

class SomeClass:
    pass

class SubSomeClass(SomeClass):
    pass

class OtherClass:
    pass

class SomeModel(BaseModel):
    cls: Type[SomeClass]

# here I can put either `SomeClass` or its subclasses
validated_some = SomeModel(cls=SubSomeClass)

# this would cause ValidationError
SomeModel(cls=OtherClass)
"""
pydantic.error_wrappers.ValidationError: 1 validation error for SomeModel
cls
  subclass of SomeClass expected (type=type_error.subclass; expected_class=SomeClass)
"""

现在在我的测试中,我尝试使用MagicMock 模拟我的SomeClass,但我无法创建一个模拟的类对象,它就像SomeClass 的子类一样。 p>

我尝试了以下方法:

>>> type(Mock(spec=SomeClass))
<class 'unittest.mock.Mock'> # doesn't pass validation
class MockSomeClass(SomeClass, MagicMock):
    """Mocked SomeClass"""

    def __init__(self, *args, **kwargs):
        pass

实例化时不返回MagicMock 实例,即MockSomeClass()

基本上我需要一些类似的东西:

>>> type(mocked_some_class)
<class 'type'>
>>> import inspect
>>> inspect.getmro(mocked_some_class)
(..., <class '__main__.SomeClass'>, ...)
>>> mocked_some_class()
<MagicMock id='...'>

【问题讨论】:

  • 你能展示你的实际测试吗?我不确定我是否理解在测试的哪个阶段出现验证。

标签: python python-unittest pydantic


【解决方案1】:

这是我最终做的:

from unittest.mock import Mock

class MockSomeClass(SomeClass, Mock):
    """Mocked SomeClass class"""

    def __new__(cls, *args, **kwargs):
        return MagicMock()

现在所有检查都通过了:

>>> type(MockSomeClass)
<class 'type'>

>>> inspect.getmro(MockSomeClass)
(<class '__main__.MockSomeClass'>, <class '__main__.SomeClass'>, <class 'unittest.mock.Mock'>, ...)

>>> MockSomeClass()
<MagicMock id='...'>

希望它对某人有用! :)

【讨论】:

  • “Mock”对象从何而来? :) 谢谢!
  • @sg_sg94 嘿,对不起,我应该添加导入。现在更新我的答案
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-12-05
  • 2012-02-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多