在python中进行测试时,如何删除装饰器的效果?[重复]
问题内容:
这个问题已经在这里有了答案 :
如何在python中模拟导入的pypi库使用的函数调用 (2个答案)
5年前关闭。
我retry
在python的某些代码中使用装饰器。但我想通过消除其影响来加快测试速度。
我的代码是:
@retry(subprocess.CalledProcessError, tries=5, delay=1, backoff=2, logger=logger)
def _sftp_command_with_retries(command, pem_path, user_at_host):
# connect to sftp, blah blah blah
pass
测试时如何去除装饰器的效果?我无法创建未经装饰的版本,因为我正在测试使用该版本的更高级别的功能。
由于retry
使用time.sleep
了后退功能,因此理想情况下我可以打补丁,time.sleep
但是由于这是在装饰器中进行的,因此我认为这是不可能的。
有什么方法可以加快使用此功能的测试代码的速度吗?
更新资料
我基本上是在尝试测试使用此功能的高层函数,以确保它们捕获到抛出的任何异常_sftp_command_with_retries
。由于retry
装饰器将传播它们,因此我需要一个更复杂的模拟。
因此,从这里我可以看到如何模拟装饰器。但是现在我需要知道如何编写本身就是装饰器的模拟程序。它需要调用_sftp_command_with_retries
,如果引发异常,则将其传播,否则返回返回值。
导入我的函数后添加此功能不起作用:
_sftp_command_with_retries = _sftp_command_with_retries.__wrapped__
问题答案:
在retry
您使用的装饰是建立在顶部decorator.decorator
实用的装饰,如果未安装包一个简单的回退。
结果具有一个__wrapped__
属性,可让您访问原始功能:
orig = _sftp_command_with_retries.__wrapped__
如果decorator
未安装, 并且 您使用的是3.2之前的Python版本,则该属性将不存在;您必须手动进入装饰器闭合:
orig = _sftp_command_with_retries.__closure__[1].cell_contents
(索引0处的闭包是retry_decorator
在调用retry()
自身时产生的)。
需要注意的是decorator
被列为依赖retry
包的元数据,如果你安装它pip
的decorator
包会被自动安装。
您可以使用try...except
:
try:
orig = _sftp_command_with_retries.__wrapped__
except AttributeError:
# decorator.decorator not available and not Python 3.2 or newer.
orig = _sftp_command_with_retries.__closure__[1].cell_contents
请注意,您 始终
可以time.sleep()
使用模拟补丁。装饰器代码将使用该模拟程序,因为它引用了模块源代码中的“全局”time
模块。
或者,您可以修补retry.api.__retry_internal
:
import retry.api
def dontretry(f, *args, **kw):
return f()
with mock.patch.object(retry.api, '__retry_internal', dontretry):
# use your decorated method
这会将执行实际重试的功能临时替换为直接调用原始功能的功能。