我有以下代码片段:类 Client 中的 http post 方法 _file_upload,并将文件内容准备为 multipart/form-data。现在我必须使用 unittest.mock / mock patch 装饰器编写单元测试
url = '/services/url'
files = {'values': {'filename': file_name, 'content': file_content}}
params = {'param1':'0', 'param2':'setupdata'}
boundary = '-----------------Sample'
# Encoding file data as multipart/form-data
data = self._encode_multipart_formdata(files, params, boundary)
# Making HTTP Post
result = self._file_upload(url, self.credentials['current.user'], self.credentials['previous.password'], data, boundary)
def _encode_multipart_formdata(self, FILES, PARAMS, BOUNDARY_STR):
CHAR_ENCODING = "utf-8"
CRLF = bytes("\r\n", CHAR_ENCODING)
L = []
for (key, value) in FILES.items():
filename = value['filename']
content = value['content']
L.append(bytes('--' + BOUNDARY_STR, CHAR_ENCODING))
L.append(bytes('Content-Disposition: form-data; name="%s"; filename="%s"' % (key, filename), CHAR_ENCODING))
L.append(bytes('Content-Type: application/octet-stream', CHAR_ENCODING))
L.append(b'')
L.append(content)
for (key, value) in PARAMS.items():
L.append(bytes("--" + BOUNDARY_STR, CHAR_ENCODING))
L.append(bytes('Content-Disposition: form-data; name="%s"' % key, CHAR_ENCODING))
L.append(b'')
L.append(bytes(value, CHAR_ENCODING))
L.append(bytes('--' + BOUNDARY_STR + '--', CHAR_ENCODING))
L.append(b'')
body = CRLF.join(L)
return body
def _file_upload(self, URL, USER, PASSWORD, DATA, BOUNDARY_STR):
#for Digest Authentication
password_mgr = urllib.request.HTTPPasswordMgrWithDefaultRealm()
password_mgr.add_password(realm=None, uri=URL, user=USER, passwd=PASSWORD)
auth_handler = urllib.request.HTTPDigestAuthHandler(password_mgr)
opener = urllib.request.build_opener(auth_handler)
urllib.request.install_opener(opener)
#for POST request
req = urllib.request.Request(URL)
req.add_header("Content-Type", "multipart/form-data; boundary=%s" % BOUNDARY_STR)
try:
with urllib.request.urlopen(req, DATA) as res:
if res.getcode() != 200:
raise exception.UnexpectedHTTPResponseError(res, 'upload_error')
else:
status = res.read()
#print(status) => 200
except urllib.error.HTTPError as err:#for errors
raise exception.UnexpectedHTTPResponseError(err, 'upload_error')
except urllib.error.URLError as err:#for errors
raise exception.UnexpectedHTTPResponseError(err, 'upload_error')
return status
是否可以模拟编码?我如何模拟摘要?
我准备了下一个测试,但它并不完全有效,没有覆盖所有行。
import urllib.request
import unittest
from unittest.mock import patch, MagicMock
class TestUrlopen(unittest.TestCase):
@patch('urllib.request.urlopen')
def test_cm(self, mock_urlopen):
utils_mock = MagicMock()
# Configuration I need for the Client class
utils_mock.config = {'device': 'TestDevice', 'type': 'Test',
'cam_credentials': {'current.user': 'TestUser', 'current.password': 'TestPassword'}}
utils_mock.getcode.return_value = 200
utils_mock.read.return_value = 'contents'
utils_mock.__enter__.return_value = cm
mock_urlopen.return_value = cm
with urllib.request.urlopen('http://foo') as response:
self.assertEqual(response.getcode(), 200)
self.assertEqual(response.read(), 'contents')