无法使用 Python 的 mock.patch 模拟 urllib2.urlopen
Not able to mock urllib2.urlopen using Python's mock.patch
下面是我的 api.py 模块的代码片段
# -*- coding: utf-8 -*-
from urllib2 import urlopen
from urllib2 import Request
class API:
def call_api(self, url, post_data=None, header=None):
is_post_request = True if (post_data and header) else False
response = None
try:
if is_post_request:
url = Request(url = url, data = post_data, headers = header)
# Calling api
api_response = urlopen(url)
response = api_response.read()
except Exception as err:
response = err
return response
我正在尝试在上述模块的 unittest
中模拟 urllib2.urlopen
。我写了
# -*- coding: utf-8 -*-
# test_api.py
from unittest import TestCase
import mock
from api import API
class TestAPI(TestCase):
@mock.patch('urllib2.Request')
@mock.patch('urllib2.urlopen')
def test_call_api(self, urlopen, Request):
urlopen.read.return_value = 'mocked'
Request.get_host.return_value = 'google.com'
Request.type.return_value = 'https'
Request.data = {}
_api = API()
assert _api.call_api('https://google.com') == 'mocked'
在我 运行 单元测试之后,我得到一个异常
<urlopen error unknown url type: <MagicMock name='Request().get_type()' id='159846220'>>
我错过了什么?请帮帮我。
你打错了补丁:看看 Where to patch.
在api.py
中
from urllib2 import urlopen
from urllib2 import Request
您在文件中创建了对 urlopen
和 Request
的本地引用。通过 mock.patch('urllib2.urlopen')
,您正在修补原始参考并保持 api.py
的不变。
所以,用
替换你的补丁
@mock.patch('api.Request')
@mock.patch('api.urlopen')
应该可以解决您的问题....但还不够。
在您的测试用例中 api.Request
未被使用,但 urllib2.urlopen()
通过使用补丁版本创建 Request
:这就是为什么 Request().get_type()
是 MagicMock
.
要获得完整的修复,您应该完全更改您的测试。先上代码:
@mock.patch('api.urlopen', autospec=True)
def test_call_api(self, urlopen):
urlopen.return_value.read.return_value = 'mocked'
_api = API()
self.assertEqual(_api.call_api('https://google.com'), 'mocked')
urlopen.assert_called_with('https://google.com')
现在澄清一下...在你的测试中你没有调用 Request()
因为你只传递了第一个参数,所以我删除了无用的补丁。此外,您正在修补 urlopen
函数而不是 urlopen
对象,这意味着您想要模拟的 read()
方法是 urlopen()
调用的对象 return 的方法。
最后,我添加了对 urlopen
调用和 autospec=True
的检查,这始终是一个好习惯。
下面是我的 api.py 模块的代码片段
# -*- coding: utf-8 -*-
from urllib2 import urlopen
from urllib2 import Request
class API:
def call_api(self, url, post_data=None, header=None):
is_post_request = True if (post_data and header) else False
response = None
try:
if is_post_request:
url = Request(url = url, data = post_data, headers = header)
# Calling api
api_response = urlopen(url)
response = api_response.read()
except Exception as err:
response = err
return response
我正在尝试在上述模块的 unittest
中模拟 urllib2.urlopen
。我写了
# -*- coding: utf-8 -*-
# test_api.py
from unittest import TestCase
import mock
from api import API
class TestAPI(TestCase):
@mock.patch('urllib2.Request')
@mock.patch('urllib2.urlopen')
def test_call_api(self, urlopen, Request):
urlopen.read.return_value = 'mocked'
Request.get_host.return_value = 'google.com'
Request.type.return_value = 'https'
Request.data = {}
_api = API()
assert _api.call_api('https://google.com') == 'mocked'
在我 运行 单元测试之后,我得到一个异常
<urlopen error unknown url type: <MagicMock name='Request().get_type()' id='159846220'>>
我错过了什么?请帮帮我。
你打错了补丁:看看 Where to patch.
在api.py
中
from urllib2 import urlopen
from urllib2 import Request
您在文件中创建了对 urlopen
和 Request
的本地引用。通过 mock.patch('urllib2.urlopen')
,您正在修补原始参考并保持 api.py
的不变。
所以,用
替换你的补丁@mock.patch('api.Request')
@mock.patch('api.urlopen')
应该可以解决您的问题....但还不够。
在您的测试用例中 api.Request
未被使用,但 urllib2.urlopen()
通过使用补丁版本创建 Request
:这就是为什么 Request().get_type()
是 MagicMock
.
要获得完整的修复,您应该完全更改您的测试。先上代码:
@mock.patch('api.urlopen', autospec=True)
def test_call_api(self, urlopen):
urlopen.return_value.read.return_value = 'mocked'
_api = API()
self.assertEqual(_api.call_api('https://google.com'), 'mocked')
urlopen.assert_called_with('https://google.com')
现在澄清一下...在你的测试中你没有调用 Request()
因为你只传递了第一个参数,所以我删除了无用的补丁。此外,您正在修补 urlopen
函数而不是 urlopen
对象,这意味着您想要模拟的 read()
方法是 urlopen()
调用的对象 return 的方法。
最后,我添加了对 urlopen
调用和 autospec=True
的检查,这始终是一个好习惯。