我想在模块中模拟对urllib.request.urlopen
的调用。当它是单个文件时它可以工作,但是当我把它放在一个包中并导入包__init__.py
中的模块时,我就不能再把它嘲笑了。
想象一下,test
包中有两个模块:
module.py
from urllib.request import urlopen
def do_it():
print(urlopen.__module__)
urlopen('test')
module_test.py
from unittest import mock
from .module import do_it
def test_not_working():
with mock.patch('urllib.request.urlopen', lambda url: print(url)):
do_it()
def test_plain():
with mock.patch('test.module.urlopen', lambda url: print(url)):
do_it()
test_not_working
打印urllib.request
作为urlopen
的模块,因为我修补了测试模块中的本地urlopen
函数,测试失败,因为test
不是有效的网址
test_plain
打印.module
,因为我成功修补urlopen
,测试成功并打印test
。
我的问题是我已将.module
移到了一个包中,因为我想将我创建的多个文件分组。它现在看起来像这样:
module
__init__.py
from .module import do_it
module.py
(与之前的module.py
相同) test_module.py
from unittest import mock
from .module import do_it
def test_packaged_fails():
with mock.patch('test.module.urlopen', lambda url: print(url)):
do_it()
def test_packaged_works():
with mock.patch('test.module.module.urlopen', lambda url: print(url)):
do_it()
前两个测试保持不变,但test_packaged
打印urllib.request
,因第一次测试失败,因为网址test
无效。
我知道我没有模仿urlopen
,因为它显然不使用test.module.urlopen
而是使用test.module.module.urlopen
。
我不知道如何解决这个问题,因为该模块只是开源项目(OpenMensa Parsers)中的众多模块之一。 Aachener parser是一个包含多个文件的包,而不是像其他解析器一样的单个文件模块 当我想要upgrade snapshots进行回归测试时,会出现上述问题。它应该缓存解析器发出的所有请求,以便稍后可以再现测试,即使网站发生了变化。
我有以下限制:
test.module.module.urlopen
)的路径,因为我也希望将快照生成用于其他解析器。urllib.request.urlopen
保持一致以与其他解析器保持一致。do_it()
。我从另一个模块调用一个函数,该模块从不同的解析器模块动态导入do_it()
,然后调用它。为简单起见,我将保留上面的最小例子。如果我不知道调用它的子包,我如何在包中修补urlopen
?
答案 0 :(得分:0)
解决方法是修改module/module.py
中的import语句:
from urllib import request
def do_it():
print(urlopen.__module__)
request.urlopen('test')
这使得可以使用:
来模拟它with mock.patch('urllib.request.urlopen', lambda url: print(url)):
do_it()
但是,这是一种需要更改被测模块的解决方法。我仍然对找到直接导入urlopen
并在那里模拟它的子模块的方式感兴趣。
答案 1 :(得分:0)
如果您知道哪个函数使用urlopen
,并且您知道它通过模块级urlopen
访问from urllib.request import urlopen
,那么您可以通过函数的全局变量dict执行补丁:< / p>
with mock.patch.dict(do_it.__globals__, urlopen=whatever):
do_whatever_with(do_it)
最终,在Python中进行模拟仍然需要大量有关测试代码导入的实现细节知识。