![](/img/trans.png)
[英]Monkey Patch private instance function in python 2 with calling old function
[英]Python monkey patch private function
我有一个带有函数的模块(称为a()
),该模块调用了在同一模块中定义的另一个函数(称为__b()
)。 __b()
是一个通过urllib2
与网站__b()
并获取一些数据的函数。 现在,我正在尝试测试a()
,但是当然不希望我的单元测试与公共互联网对话。 因此,我在考虑是否可以用返回固定数据的函数来修补__b()
,然后可以为a()
编写测试。
更具体地说,我的模块有点像:
def a():
return __b("someval")
def __b(args):
return something_complex_with_args
所以现在我想测试a()
,但是我需要猴子修补__b
。 问题在于,A)有关猴子修补的绝大多数信息都适用于类的方法,而不适用于模块中的函数,以及B)我想进行猴子修补的函数是私有的。 我愿意将__b
更改为非私有,如果它使该过程更可行,但宁愿不这样做。
有什么建议吗?
编辑:就目前情况而言,测试类如下所示:
from unittest import TestCase
import mymodule
def newfn(args):
return {"a" : "b"}
mymodule._b = newfn
class TestMyModule(TestCase):
def test_basic(self):
print(mymodule.a('somearg'))
当我运行此命令时,如果根本没有完成猴子修补,则会看到输出,而不是看到{'a': 'b'}
被打印出来。
我似乎无法重现您的问题(我稍微调整了您的示例,因为它根本没有按原样运行)。 您是否只是输错了某些内容(例如mymodule._b
而不是mymodule.__b
)?
mymodule.py :
def a(x):
return __b("someval")
def __b(args):
return "complex_thingy: {}".format(args)
mytest.py :
from unittest import TestCase
import mymodule
def newfn(args):
return {"a" : "b"}
mymodule.__b = newfn
class TestMyModule(TestCase):
def test_basic(self):
print(mymodule.a('somearg'))
输出 :
C:\TEMP>python -m unittest mytest
{'a': 'b'}
.
----------------------------------------------------------------------
Ran 1 test in 0.001s
OK
C:\TEMP>
似乎工作正常。
或在单元测试之外:
mytest2.py :
import mymodule
def newfn(args):
return {"a" : "b"}
mymodule.__b = newfn
print(mymodule.a('somearg'))
输出 :
C:\TEMP>python mytest2.py
{'a': 'b'}
C:\TEMP>
如果您的模块被命名为“ foo”,那么以下应该可以工作。
import foo
def patched_version():
return 'Hello'
foo.__b = patched_version
print (foo.a())
foo.py在哪里
def a():
return __b()
def __b():
return 'Goodbye'
我遇到了同样的问题,但最终找到了解决方案。 问题是在unittest.TestCase类中使用猴子补丁时。 这是可行的解决方案:
如果您使用的是Python 2,则需要使用easy_install或其他方式安装“ mock”库(http://www.voidspace.org.uk/python/mock/)。 该库已经与Python 3捆绑在一起。
代码如下所示:
from mock import patch
class TestMyModule(TestCase):
def test_basic(self):
with patch('mymodule._b') as mock:
mock.return_value={"a" : "b"} # put here what you want the mock function to return. You can make multiple tests varying these values.
#keep the indentation. Determines the scope for the patch.
print(mymodule.a('somearg'))
尽管与制作模拟函数(其中我们可以模仿实际的子函数_b()并使其具有根据不同参数返回不同值的逻辑)相比,这种方法似乎似乎不那么方便,但是我们不必要地增加了出错的机会。 在这种方法中,我们只是硬编码我们要让模拟函数返回的内容,并测试我们要测试的实际函数,即a()。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.