python-3.x 在MagicMock上使用Monkeypatching '__call__'

o7jaxewo  于 2023-02-26  发布在  Python
关注(0)|答案(1)|浏览(114)

假设我定义了一个helper方法来monkeypatch对现有对象__call__行为的简单修改:

def and_print_on_call(instance):
  class AndPrintOnCall(type(instance)):
    def __call__(self, *args, **kwarg):
      print('printed!')
      return super().__call__(*args, **kwarg)

  instance.__class__ = AndPrintOnCall

如果我将其应用于一个典型的类示例,它将按预期工作:

class Foo:
  def __call__(self):
    print('foo!')
foo = Foo()

and_print_on_call(foo)
foo()  # Prints "printed!" then "foo!"

但如果我将其应用于MagicMock示例,则不会:

foo = unittest.mock.MagicMock()
foo.side_effect = lambda: print('foo!')

and_print_on_call(foo)
foo()  # Prints only "foo!"

为什么?MagicMock有什么特别之处,调用它的示例显然不像典型类那样引用__class__.__call__
为了提供一些更广泛的背景:我试图创建一个深度复制模拟,以便处理可变参数(类似于这里讨论的内容,尽管提供的解决方案都不能满足我的特定需求)。在真实的实现中,print('printed!')语句将代替复制逻辑。

m2xkgtsf

m2xkgtsf1#

模拟截距__class__赋值:

def __setattr__(self, name, value):
    ...
    elif name == '__class__':
        self._spec_class = value
        return

所以instance.__class__ = AndPrintOnCall实际上并不起作用。

相关问题