python - MagicMock 如何在调用随机方法时避免抛出 AttributeError?

标签 python mocking pytest magicmock

在 Python 中,如果您调用一个不存在的方法,它会抛出一个 AttributeError。例如

>>> class A:
...     def yo(self):
...             print(1)
... 
>>> a = A()
>>> a.yo()
1
>>> a.hello()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'A' object has no attribute 'hello'

在下面的代码中,MagicMock 类没有名为 hello 的函数,或者没有为方法 hello 创建补丁。仍然在下面的代码不会抛出 AttributeError

>>> from unittest.mock import MagicMock 
>>> obj = MagicMock()
>>> obj.hello()
<MagicMock name='mock.hello()' id='4408758568'>

MagicMock 如何做到这一点?我如何创建一个可以在任何方法(可能未定义)被调用时执行操作的类?

最佳答案

Python 数据模型记录了一个钩子(Hook),__getattr__ ,当属性访问无法以通常的方式解析时,应调用它。模拟使用它来返回一个新的模拟实例——即模拟将未知属性定义为 factories .

以更简单的方式重现 mock 的实现,您只需将 __getattr____call__ 转换为工厂函数:

class M:
    def __call__(self):
        return M()
    def __getattr__(self, name):
        return M()

示例用法:

>>> mock = M()
>>> mock.potato
<__main__.M at 0xdeadbeef>
>>> mock.potato()
<__main__.M at 0xcafef00d>

How is MagicMock able to do this?

这部分不是特定于 MagicMock 的,普通的 Mock 也会做同样的事情(名称中的“魔术”只是指允许更好地模拟的附加功能magic methods)。 MagicMock inherits such behavior from one of the base classes :

>>> MagicMock.mro()
[unittest.mock.MagicMock,
 unittest.mock.MagicMixin,
 unittest.mock.Mock,
 unittest.mock.CallableMixin,
 unittest.mock.NonCallableMock,  # <--- this one overrides __getattr__!
 unittest.mock.Base,
 object]

How can I create a class that can perform an action when any method (which might not be defined) is called on it?

这取决于您是想在普通属性访问之前还是之后。如果你想排在前面,你应该定义__getattribute__ ,在搜索类/实例 namespace 之前无条件地调用它来实现属性访问。但是,如果您想对普通属性(即对象 __dict__ 中的属性)和 descriptors 采取较低的优先级, 那么你应该像前面讨论的那样定义 __getattr__

关于python - MagicMock 如何在调用随机方法时避免抛出 AttributeError?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52978673/

相关文章:

python - 在 ubuntu 中设置 OpenCV 2.3 w/python 绑定(bind)

python - python中的问题,同时合并2个文本文件并将它们汇总到一个新的文本文件中

python - Pandas:数据帧列中 n 个连续元素的组总和

ruby-on-rails - 使用 RSpec 和模拟测试 after_commit

python - 在 Blender 中使用脚本创建 PDF

c# - 单元测试静态实用程序类

python - 为在子进程中运行的 python 功能测试运行假的 redis

python - 在 pytest 装置中导入应用程序时出错

python - pytest 无法在 Python 2.7 下处理 README 中 doctest 中的 Unicode

测试属性的 Pythonic 方法?