I have the following function and it is a generic function which will make API call based on the input hostname and data. It will construct http request to make API and will return the response. This function will throw four types of exception(invalid URL, timeout, auth error and status check). How can I Mcok and Test the exception raised in API call using pytest? Which will be the best method to test the exceptions raised from API call?
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)
If i call this function
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
i will get a response like following
b"<response status = 'success'><result><key>mykey</key></result></response>"
You can mock error raising via side_effect
parameter:
Alternatively side_effect can be an exception class or instance. In this case the exception will be raised when the mock is called.
In your case, this can be used like this (assuming call_api
is defined in module 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'
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With