使用Pytest在函数中引发模拟异常

时间:2018-06-21 09:15:34

标签: python-3.x exception mocking urllib pytest

我具有以下功能,这是一个通用功能,它将根据输入的主机名和数据进行API调用。它将构造http请求以制作API并返回响应。此函数将引发四种类型的异常(无效的URL,超时,身份验证错误和状态检查)。如何使用pytest进行Mcok和测试API调用中引发的异常?哪种方法是测试API调用引发的异常的最佳方法?

import ssl
import urllib
import urllib.request
import urllib.error
import xml
import xml.etree.ElementTree as ET

def call_api(hostname, data):
    '''Function to make API call
    '''
    # Todo:
    # Context to separate function?
    # check response for status codes and return reponse.read() if success
    #   Else throw exception and catch it in calling function
    error_codes = {
         "1": "Unknown command",
         "6": "Bad Xpath",
         "7": "Object not present",
         "8": "Object not unique"
     }
    url = "http://" + hostname + "/api"
    encoded_data = urllib.parse.urlencode(data).encode('utf-8')
    try:
        response = urllib.request.urlopen(url, data=encoded_data, 
timeout=10).read()
        root = ET.fromstring(response)
        if root.attrib.get('status') != "success":
            Errorcode = root.attrib.get('code')
            raise Exception(pan_error_codes.get(Errorcode, "UnknownError"), 
response)
        else:
            return response
    except urllib.error.HTTPError as e:
        raise Exception(f"HttpError: {e.code} {e.reason} at {e.url}", None)
    except urllib.error.URLError as e:
       raise Exception(f"Urlerror: {e.reason}", None)

如果我调用此函数

def create_key(hostname, username, password):
hostname = 'myhost ip'
data = {
    'type': 'keygen',
    'username': username,
    'password': password
}
username = 'myuser'
password = 'password'
response = call_api(hostname, data)
return response

我将得到如下响应

b"<response status = 'success'><result><key>mykey</key></result></response>"

1 个答案:

答案 0 :(得分:0)

您可以通过side_effect参数模拟错误提示:

  

或者, side_effect 可以是异常类或实例。在这种情况下,调用模拟程序时将引发异常。

在您的情况下,可以这样使用(假设call_api在模块foo中定义):

import pytest
from unittest.mock import patch

def test_api():
    with patch('foo.call_api', side_effect=Exception('mocked error')):
        with pytest.raises(Exception) as excinfo:
            create_key('localhost:8080', 'spam', 'eggs')
        assert excinfo.value.message == 'mocked error'