如何使用模拟对 urllib 进行单元测试

时间:2021-05-18 21:59:40

标签: python unit-testing http mocking urllib

我有以下代码片段:类 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')

0 个答案:

没有答案
相关问题