我想用python测试一个函数,但是它依赖于一个模块级的“private”函数,我不想调用它,但是在重写/模拟它时遇到了困难。场景:
在模块.py在
_cmd(command, args):
# do something nasty
function_to_be_tested():
# do cool things
_cmd('rm', '-rf /')
return 1
试验_模块.py在
^{pr2}$理想情况下,在这个测试中,我不想调用命令。我看了一些其他的线索,我尝试了以下方法,但没有成功:
test_function():
def _cmd(command, args):
# do nothing
pass
module._cmd = _cmd
虽然检查module。使用mock:
from mock import patch
def _cmd_mock(command, args):
# do nothing
pass
@patch('module._cmd', _cmd_mock)
test_function():
...
在检查模块时提供正确的引用。尽管“function_to_be_tested”仍然使用原始的_cmd(它做了一些令人讨厌的事情就证明了这一点)。在
这很棘手,因为cmd是一个模块级函数,我不想把它移到一个模块中
[免责声明]
这个问题中发布的合成示例起作用,所描述的问题来自于生产代码中的具体实现。也许这个问题应该作为话题外的话题结束,因为这个问题是不可重复的。在
[注意]对于不耐烦的人,解决方案在答案的最后。在
不管怎样,这个问题给了我一个很好的思考点:当我们不能访问引用所在的变量时,如何修补方法引用?在
很多时候我发现了这样的问题。有很多方法可以解决这个问题
在这两种情况下,重构代码可能是最好的方法,但是如果我们使用的是一些遗留代码,或者decorator是第三方decorator呢?在
好吧,我们已经有了背景,但是我们使用的是python,在python中没有什么是不可能的。我们需要的只是函数/方法的引用来修补,而不是修补它的引用,我们可以修补
__code__
:是的,我说的是修补字节码而不是函数。在举个真实的例子。我使用的默认参数case很简单,但它可以在decorator case中使用。在
输出:
好的,在这个例子中,我们可以通过传递
^{pr2}$cmd_fake
来测试do_work
,但是在某些情况下不可能这样做:例如,如果我们需要调用这样的东西,该怎么办:我们可以做的是修补}
cmd.__code__
,而不是{所以要遵守规则
给出以下输出:
此外,如果我们想使用模拟,我们可以添加以下行:
打印出来的
也许我说完了。。。但OP仍在等待他的问题的解决
现在我要说的是,除非你背对着墙,否则不要使用这个技巧。测试应该易于理解和调试。。。试着调试这样的东西,你会发疯的!在
相关问题 更多 >
编程相关推荐