gpt4 book ai didi

python - isinstance 检查中使用的模拟类具有动态属性

转载 作者:太空宇宙 更新时间:2023-11-03 17:51:46 29 4
gpt4 key购买 nike

某些类在类级别(在 __init__ 或任何其他函数之外)定义其属性(也称为字段)。有些类在其 __init__ 函数中定义它们,甚至从其他函数中定义它们。有些类(class)同时使用这两种方法。

class MyClass(object):
foo = 'foo'
def __init__(self, *args, **kwargs):
self.bar = 'bar'

问题是,当您使用 dir 时,如果您传入该类的实例,它只包含 'bar'

>>> dir(MyClass)
['__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'foo']
>>> myInstance = MyClass()
>>> dir(myInstance)
['__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'bar', 'foo']

(滚动到最右侧查看差异)

我遇到了一种情况,我需要避免实例化 MyClass 但我想将其用作 spec 设置(以传递 isinstance检查)在单元测试中的 mock.patch 调用中。

@mock.patch('mypackage.MyClass', spec=MyClass)
def test_thing_that_depends_on_MyClass(self, executeQueryMock):
# uses 'thing' here, which uses MyClass.bar ...

这样做会导致:

AttributeError: Mock object has no attribute 'bar'

这是有道理的,因为 mock docs说:

spec: This can be either a list of strings or an existing object (a class or instance) that acts as the specification for the mock object. If you pass in an object then a list of strings is formed by calling dir on the object (excluding unsupported magic attributes and methods). Accessing any attribute not in this list will raise an AttributeError.

即使我实例化 MyClass,我也会收到不同的错误。

@mock.patch('mypackage.MyClass', spec=MyClass())
def test_thing_that_depends_on_MyClass(self, executeQueryMock):
# uses 'thing' here, which uses MyClass.bar ...

原因:

TypeError: 'NonCallableMagicMock' object is not callable

我并不真正关心严格限制我允许访问哪些功能/属性;我实际上想要正常的 MagicMock 行为,它可以让您在没有 AttributeError 的情况下调用任何内容。似乎使用 spec 使这一点变得严格,即使我只是使用 spec 来通过 isinstance 检查。

问题:

如何正确模拟在 isinstance 检查中使用的此类,并且该类具有未在类级别定义的属性?

最佳答案

鉴于您只想通过 isinstance 检查,我认为最简单的解决方案是为 mock.patch.object 编写一个快速包装器来设置 返回的模拟的 __class__ 属性。

def my_patch(obj, attr_name):
fake_class = mock.MagicMock()
fake_instance = fake_class.return_value # calling a class returns an instance.
fake_instance.__class__ = getattr(obj, attr_name)
return mock.patch.object(obj, attr_name, fake_class)

它的使用方式类似于mock.patch.object:

@my_patch(some_module, 'MyClass')
def test_something(self, fake_my_class):
...

但是假对象应该通过 isinstance 检查,就像规范的模拟一样。

关于python - isinstance 检查中使用的模拟类具有动态属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28997078/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com