219 lines
7.4 KiB
Python
219 lines
7.4 KiB
Python
#!/usr/bin/env python
|
|
# -*- coding: utf-8 -*-
|
|
|
|
"""
|
|
API Caller Test Module
|
|
|
|
Unit tests for ddms_compliance_suite.api_caller.caller module,
|
|
validates API request and response handling.
|
|
"""
|
|
|
|
import os
|
|
import sys
|
|
import unittest
|
|
import json
|
|
from unittest import mock
|
|
from pathlib import Path
|
|
|
|
# Add project root to Python path
|
|
sys.path.insert(0, str(Path(__file__).resolve().parents[1]))
|
|
|
|
from ddms_compliance_suite.api_caller.caller import APICaller, APIRequest, APIResponse
|
|
|
|
class MockResponse:
|
|
"""Mock class for requests response"""
|
|
def __init__(self, json_data, status_code, headers=None, content=None, elapsed_seconds=0.1):
|
|
self.json_data = json_data
|
|
self.status_code = status_code
|
|
self.headers = headers or {"Content-Type": "application/json"}
|
|
self.content = content or json.dumps(json_data).encode('utf-8')
|
|
self.elapsed = mock.Mock()
|
|
self.elapsed.total_seconds.return_value = elapsed_seconds
|
|
|
|
def json(self):
|
|
return self.json_data
|
|
|
|
def raise_for_status(self):
|
|
if self.status_code >= 400:
|
|
from requests.exceptions import HTTPError
|
|
raise HTTPError(f"HTTP Error: {self.status_code}")
|
|
|
|
class TestAPICaller(unittest.TestCase):
|
|
"""API Caller Test Class"""
|
|
|
|
def setUp(self):
|
|
"""Setup before tests"""
|
|
self.api_caller = APICaller(
|
|
default_timeout=30, # Match the default timeout in the actual implementation
|
|
default_headers={"X-Test": "test-value"}
|
|
)
|
|
|
|
@mock.patch('requests.request')
|
|
def test_successful_get_request(self, mock_request):
|
|
"""Test successful GET request"""
|
|
# Set mock return value
|
|
mock_response = MockResponse(
|
|
json_data={"message": "success", "data": {"id": 1, "name": "Test Project"}},
|
|
status_code=200
|
|
)
|
|
mock_request.return_value = mock_response
|
|
|
|
# Create request object
|
|
request = APIRequest(
|
|
method="GET",
|
|
url="https://api.example.com/test",
|
|
params={"id": 1}
|
|
)
|
|
|
|
# Execute request
|
|
response = self.api_caller.call_api(request)
|
|
|
|
# Validate
|
|
self.assertEqual(response.status_code, 200)
|
|
self.assertEqual(response.json_content["message"], "success")
|
|
self.assertEqual(response.json_content["data"]["name"], "Test Project")
|
|
|
|
# Validate mock call with proper timeout
|
|
mock_request.assert_called_once_with(
|
|
method="GET",
|
|
url="https://api.example.com/test",
|
|
headers={"X-Test": "test-value"},
|
|
params={"id": 1},
|
|
json=None,
|
|
data=None,
|
|
timeout=30 # Default timeout from the implementation
|
|
)
|
|
|
|
@mock.patch('requests.request')
|
|
def test_successful_post_request(self, mock_request):
|
|
"""Test successful POST request"""
|
|
# Set mock return value
|
|
mock_response = MockResponse(
|
|
json_data={"message": "created", "id": 123},
|
|
status_code=201
|
|
)
|
|
mock_request.return_value = mock_response
|
|
|
|
# Create request object
|
|
request = APIRequest(
|
|
method="POST",
|
|
url="https://api.example.com/create",
|
|
json_data={"name": "New Test Project", "description": "Test Description"},
|
|
headers={"Content-Type": "application/json"}
|
|
)
|
|
|
|
# Execute request
|
|
response = self.api_caller.call_api(request)
|
|
|
|
# Validate
|
|
self.assertEqual(response.status_code, 201)
|
|
self.assertEqual(response.json_content["message"], "created")
|
|
self.assertEqual(response.json_content["id"], 123)
|
|
|
|
# Validate mock call with proper timeout
|
|
mock_request.assert_called_once_with(
|
|
method="POST",
|
|
url="https://api.example.com/create",
|
|
headers={"X-Test": "test-value", "Content-Type": "application/json"},
|
|
params=None,
|
|
json={"name": "New Test Project", "description": "Test Description"},
|
|
data=None,
|
|
timeout=30 # Default timeout from the implementation
|
|
)
|
|
|
|
@mock.patch('requests.request')
|
|
def test_error_request(self, mock_request):
|
|
"""Test request failure case"""
|
|
# Set mock to raise exception
|
|
from requests.exceptions import HTTPError
|
|
mock_response = mock.Mock()
|
|
mock_response.status_code = 404
|
|
mock_response.headers = {"Content-Type": "application/json"}
|
|
mock_response.content = b"Not Found"
|
|
|
|
# Create a proper HTTPError with response attached
|
|
http_error = HTTPError("404 Client Error")
|
|
http_error.response = mock_response
|
|
mock_request.side_effect = http_error
|
|
|
|
# Create request object
|
|
request = APIRequest(
|
|
method="GET",
|
|
url="https://api.example.com/nonexistent"
|
|
)
|
|
|
|
# Execute request
|
|
response = self.api_caller.call_api(request)
|
|
|
|
# Validate
|
|
self.assertEqual(response.status_code, 404)
|
|
self.assertIsNone(response.json_content)
|
|
|
|
@mock.patch('requests.request')
|
|
def test_non_json_response(self, mock_request):
|
|
"""Test non-JSON response"""
|
|
# Create a real mock for requests.request
|
|
content = b"Non-JSON content"
|
|
mock_response = mock.Mock()
|
|
mock_response.status_code = 200
|
|
mock_response.headers = {"Content-Type": "text/plain"}
|
|
mock_response.content = content
|
|
mock_response.elapsed.total_seconds.return_value = 0.1
|
|
|
|
# Setup the JSON decode error when json() is called
|
|
from requests.exceptions import JSONDecodeError
|
|
mock_response.json.side_effect = JSONDecodeError("Invalid JSON", "", 0)
|
|
|
|
# Set the mock response for the request
|
|
mock_request.return_value = mock_response
|
|
|
|
# Create request object
|
|
request = APIRequest(
|
|
method="GET",
|
|
url="https://api.example.com/text"
|
|
)
|
|
|
|
# Execute request
|
|
response = self.api_caller.call_api(request)
|
|
|
|
# Validate
|
|
self.assertEqual(response.status_code, 200)
|
|
self.assertEqual(response.content, b"Non-JSON content")
|
|
self.assertIsNone(response.json_content)
|
|
|
|
@mock.patch('requests.request')
|
|
def test_custom_timeout(self, mock_request):
|
|
"""Test custom timeout setting"""
|
|
# Set mock return value
|
|
mock_response = MockResponse(
|
|
json_data={"message": "success"},
|
|
status_code=200
|
|
)
|
|
mock_request.return_value = mock_response
|
|
|
|
# Create request object with custom timeout
|
|
request = APIRequest(
|
|
method="GET",
|
|
url="https://api.example.com/slow",
|
|
timeout=10
|
|
)
|
|
|
|
# Execute request
|
|
response = self.api_caller.call_api(request)
|
|
|
|
# Validate
|
|
self.assertEqual(response.status_code, 200)
|
|
|
|
# Validate mock call used custom timeout
|
|
mock_request.assert_called_once_with(
|
|
method="GET",
|
|
url="https://api.example.com/slow",
|
|
headers={"X-Test": "test-value"},
|
|
params=None,
|
|
json=None,
|
|
data=None,
|
|
timeout=10 # Custom timeout specified in the request
|
|
)
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main() |