尝试模拟实例方法时的最大递归深度 [英] Max recursion depth while trying to mock instance method

查看:72
本文介绍了尝试模拟实例方法时的最大递归深度的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想模拟一个实例方法.首先,我想修改参数,然后再调用原始方法.

I want to mock an instance method. First I want to modify the arguments and then I want to call the original method.

我尝试过:

import mock

class Foo(object):
    def my_method(data):
        print(data)

def wrapped_method(data):
    return Foo.my_method(data.replace('x', 'o'))

with mock.patch.object(Foo, 'my_method', wraps=wrapped_method):
    foo = Foo()
    foo.my_method('axe')  # should print "aoe"

但是我得到了这个例外:

But I get this exception:

/home/foo/bin/python /home/foo/src/wrap-instance-method.py
Traceback (most recent call last):
  File "/home/foo/src/wrap-instance-method.py", line 15, in <module>
    foo.my_method('axe')  # should print "aoe"
  File "/home/foo/local/lib/python2.7/site-packages/mock.py", line 955, in __call__
    return _mock_self._mock_call(*args, **kwargs)
  File "/home/foo/local/lib/python2.7/site-packages/mock.py", line 1024, in _mock_call
    return self._mock_wraps(*args, **kwargs)
.....
    return self._mock_wraps(*args, **kwargs)
  File "/home/foo/src/wrap-instance-method.py", line 10, in wrapped_method
    return Foo.my_method(data.replace('x', 'o'))
  File "/home/foo/local/lib/python2.7/site-packages/mock.py", line 955, in __call__
    return _mock_self._mock_call(*args, **kwargs)
  File "/home/foo/local/lib/python2.7/site-packages/mock.py", line 960, in _mock_call
    self.called = True
RuntimeError: maximum recursion depth exceeded while calling a Python object

Process finished with exit code 1

如何调用没有递归异常包装的原始方法?

How can I call the original method which was wrapped without recursion exception?

推荐答案

您将Foo.my_method替换为调用Foo.my_method的方法,所以是的,您将获得无限递归.

You replaced the Foo.my_method with a method that calls Foo.my_method, so yes, you'll get an infinite recursion.

如果必须使用原始方法,则需要在 对其进行修补之前将其存储:

If you must have the original method, you need to store it before you patch it:

def mock_method_factory(original):
    def wrapped_method(data):
        return original(data.replace('x', 'o'))
    return wrapped_method

with mock.patch.object(Foo, 'my_method', wraps=mock_method_factory(Foo.my_method)):
    # ...

但是,wraps不处理绑定original是未绑定的函数,wrapped_method不会在self中传递.

However, wraps does not handle binding; original is an unbound function and wrapped_method won't be passed in self.

mock库可能不是这里的最佳选择.您实际上要做的是应用一个临时装饰器.子类Foo或将装饰器手动应用于Foo.my_method:

The mock library is perhaps not the best choice here. What you are essentially doing is apply a temporary decorator. Either subclass Foo or apply the decorator manually to Foo.my_method:

def mock_method_factory(original):
    def wrapped_method(self, data):
        return original(self, data.replace('x', 'o'))
    return wrapped_method

class MockedFoo(Foo):
    my_method = mock_method_factory(Foo.my_method)

foo = MockedFoo()
foo.my_method('axe')  # should print "aoe"

def mock_method_factory(original):
    def wrapped_method(self, data):
        return original(self, data.replace('x', 'o'))
    return wrapped_method

original = Foo.my_method
try:
    Foo.my_method = mock_method_factory(original)
    foo = Foo()
    foo.my_method('axe')  # should print "aoe"
finally:
    Foo.my_method = original

这篇关于尝试模拟实例方法时的最大递归深度的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆