【发布时间】:2012-12-12 08:49:45
【问题描述】:
我有一个带有函数的模块(称为a()),它调用在同一模块中定义的另一个函数(称为__b())。 __b() 是一个通过urllib2 与网站对话并获取一些数据的函数。现在我正在尝试测试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'} 被打印出来。
【问题讨论】:
-
一般来说,如果模块外的anything需要访问一个函数(包括测试),你可能不应该使用
__name格式。改用_name格式来表示它是一个内部函数,同时仍然使需要访问它的事物能够访问它。 -
名称修改 (
__x) 与 private 不同,除非您确切知道它是什么,否则您可能不应该使用它。 Python 没有数据隐藏功能。 -
@Lattyware:我知道它与私有不同,但它已尽可能接近。为什么会担心用双下划线命名它?
-
@AdamParkin 因为双下划线提供了名称修饰 - 名称被更改(查看文档了解为什么以及究竟发生了什么)。您不需要在 Python 中将内容设为私有。您的问题是一个非常清楚的例子,说明了为什么这是一个坏主意。 Python 不是 Java 或 C++,像这样写会导致错误的代码。
-
“to docs”是指 (docs.python.org/2/tutorial/classes.html#tut-private)?所以我仍然不明白为什么它通常很糟糕。也许将其移至聊天,因为它与我的问题不是特别相关?
标签: python monkeypatching