<p>当我第一次遇到这个问题时,我常常绞尽脑汁好几个小时。我找到了一个更简单的方法来处理这个问题。</p>
<p>这将完全绕过decorator,就像目标一开始甚至没有被装饰一样。</p>
<p>这个被分成两部分。我建议读下面的文章。</p>
<p><a href="http://alexmarandon.com/articles/python_mock_gotchas/" rel="noreferrer">http://alexmarandon.com/articles/python_mock_gotchas/</a></p>
<p>我经常碰到两个问题:</p>
<p>1.)在导入函数/模块之前模拟Decorator。</p>
<p>装饰器和函数是在加载模块时定义的。
如果在导入之前不模拟,它将忽略模拟。加载后,您必须执行一个奇怪的mock.patch.object,这会更加令人沮丧。</p>
<p>2)确保您模拟的是到装饰器的正确路径。</p>
<p>记住,您模拟的decorator的补丁是基于模块如何加载decorator的,而不是测试如何加载decorator的。这就是为什么我建议总是使用完整的导入路径。这使得测试变得更加容易。</p>
<p>步骤:</p>
<p>1.)模拟函数:</p>
<pre><code>from functools import wraps
def mock_decorator(*args, **kwargs):
def decorator(f):
@wraps(f)
def decorated_function(*args, **kwargs):
return f(*args, **kwargs)
return decorated_function
return decorator
</code></pre>
<p>2)嘲笑装修师:</p>
<p>2a.)内部通道。</p>
<pre><code>with mock.patch('path.to.my.decorator', mock_decorator):
from mymodule import myfunction
</code></pre>
<p>2b.)文件顶部的修补程序,或在TestCase.setUp中</p>
<pre><code>mock.patch('path.to.my.decorator', mock_decorator).start()
</code></pre>
<p>这两种方法都允许您在测试用例或其方法/测试用例中随时导入函数。</p>
<pre><code>from mymodule import myfunction
</code></pre>
<p>2.)使用单独的函数作为mock.patch的副作用。</p>
<p>现在您可以为每个要模拟的装饰器使用mock_decorator。你将不得不分别嘲笑每一个装饰,所以小心那些你错过的。</p>