Files
Airwallex/airwallex-sdk/tests/test_exceptions.py
zqq61 4f53889a8e feat: Airwallex 发卡管理后台完整实现
- 后端: FastAPI + SQLAlchemy + SQLite, JWT认证, 代理支持的AirwallexClient
- 前端: React 18 + Vite + Ant Design 5, 中文界面
- 功能: 卡片管理, 持卡人管理, 交易记录, API令牌, 系统设置, 审计日志
- 第三方API: X-API-Key认证, 权限控制
- Docker部署: docker-compose编排前后端
2026-03-15 23:05:08 +08:00

250 lines
8.1 KiB
Python

"""
Tests for the Airwallex SDK exception handling.
"""
import unittest
from unittest.mock import MagicMock
import json
from airwallex.exceptions import (
AirwallexAPIError,
AuthenticationError,
RateLimitError,
ResourceNotFoundError,
ValidationError,
ServerError,
ResourceExistsError,
AmountLimitError,
EditForbiddenError,
CurrencyError,
DateError,
TransferMethodError,
ConversionError,
ServiceUnavailableError,
create_exception_from_response
)
class TestExceptions(unittest.TestCase):
"""Tests for the exception handling system."""
def setUp(self):
"""Set up test fixtures."""
self.mock_response = MagicMock()
self.method = "GET"
self.url = "/api/v1/test"
self.kwargs = {"headers": {"Authorization": "Bearer test_token"}}
def test_exception_from_status_code(self):
"""Test creating exceptions based only on status code."""
# 401 should create AuthenticationError
self.mock_response.status_code = 401
self.mock_response.json.side_effect = ValueError("Invalid JSON")
exception = create_exception_from_response(
response=self.mock_response,
method=self.method,
url=self.url,
kwargs=self.kwargs
)
self.assertIsInstance(exception, AuthenticationError)
self.assertEqual(exception.status_code, 401)
# 404 should create ResourceNotFoundError
self.mock_response.status_code = 404
exception = create_exception_from_response(
response=self.mock_response,
method=self.method,
url=self.url,
kwargs=self.kwargs
)
self.assertIsInstance(exception, ResourceNotFoundError)
self.assertEqual(exception.status_code, 404)
# 429 should create RateLimitError
self.mock_response.status_code = 429
exception = create_exception_from_response(
response=self.mock_response,
method=self.method,
url=self.url,
kwargs=self.kwargs
)
self.assertIsInstance(exception, RateLimitError)
self.assertEqual(exception.status_code, 429)
# 400 should create ValidationError
self.mock_response.status_code = 400
exception = create_exception_from_response(
response=self.mock_response,
method=self.method,
url=self.url,
kwargs=self.kwargs
)
self.assertIsInstance(exception, ValidationError)
self.assertEqual(exception.status_code, 400)
# 500 should create ServerError
self.mock_response.status_code = 500
exception = create_exception_from_response(
response=self.mock_response,
method=self.method,
url=self.url,
kwargs=self.kwargs
)
self.assertIsInstance(exception, ServerError)
self.assertEqual(exception.status_code, 500)
def test_exception_from_error_code(self):
"""Test creating exceptions based on error code."""
self.mock_response.status_code = 400
# Test credentials_invalid (should be AuthenticationError)
self.mock_response.json.return_value = {
"code": "credentials_invalid",
"message": "Invalid credentials",
"source": "api_key"
}
exception = create_exception_from_response(
response=self.mock_response,
method=self.method,
url=self.url,
kwargs=self.kwargs
)
self.assertIsInstance(exception, AuthenticationError)
self.assertEqual(exception.error_code, "credentials_invalid")
self.assertEqual(exception.error_source, "api_key")
# Test already_exists (should be ResourceExistsError)
self.mock_response.json.return_value = {
"code": "already_exists",
"message": "Resource already exists",
"source": "id"
}
exception = create_exception_from_response(
response=self.mock_response,
method=self.method,
url=self.url,
kwargs=self.kwargs
)
self.assertIsInstance(exception, ResourceExistsError)
self.assertEqual(exception.error_code, "already_exists")
# Test amount_above_limit (should be AmountLimitError)
self.mock_response.json.return_value = {
"code": "amount_above_limit",
"message": "Amount exceeds the maximum limit",
"source": "amount"
}
exception = create_exception_from_response(
response=self.mock_response,
method=self.method,
url=self.url,
kwargs=self.kwargs
)
self.assertIsInstance(exception, AmountLimitError)
self.assertEqual(exception.error_code, "amount_above_limit")
# Test invalid_currency_pair (should be CurrencyError)
self.mock_response.json.return_value = {
"code": "invalid_currency_pair",
"message": "The currency pair is invalid",
"source": "currency_pair"
}
exception = create_exception_from_response(
response=self.mock_response,
method=self.method,
url=self.url,
kwargs=self.kwargs
)
self.assertIsInstance(exception, CurrencyError)
self.assertEqual(exception.error_code, "invalid_currency_pair")
# Test invalid_transfer_date (should be DateError)
self.mock_response.json.return_value = {
"code": "invalid_transfer_date",
"message": "The transfer date is invalid",
"source": "transfer_date"
}
exception = create_exception_from_response(
response=self.mock_response,
method=self.method,
url=self.url,
kwargs=self.kwargs
)
self.assertIsInstance(exception, DateError)
self.assertEqual(exception.error_code, "invalid_transfer_date")
# Test service_unavailable (should be ServiceUnavailableError)
self.mock_response.status_code = 503
self.mock_response.json.return_value = {
"code": "service_unavailable",
"message": "The service is currently unavailable",
}
exception = create_exception_from_response(
response=self.mock_response,
method=self.method,
url=self.url,
kwargs=self.kwargs
)
self.assertIsInstance(exception, ServiceUnavailableError)
self.assertEqual(exception.error_code, "service_unavailable")
def test_exception_string_representation(self):
"""Test the string representation of exceptions."""
self.mock_response.status_code = 400
self.mock_response.json.return_value = {
"code": "invalid_argument",
"message": "The argument is invalid",
"source": "amount"
}
exception = create_exception_from_response(
response=self.mock_response,
method=self.method,
url=self.url,
kwargs=self.kwargs
)
expected_str = "Airwallex API Error (HTTP 400): [invalid_argument] The argument is invalid (source: amount) for GET /api/v1/test"
self.assertEqual(str(exception), expected_str)
# Test without source
self.mock_response.json.return_value = {
"code": "invalid_argument",
"message": "The argument is invalid"
}
exception = create_exception_from_response(
response=self.mock_response,
method=self.method,
url=self.url,
kwargs=self.kwargs
)
expected_str = "Airwallex API Error (HTTP 400): [invalid_argument] The argument is invalid for GET /api/v1/test"
self.assertEqual(str(exception), expected_str)
if __name__ == '__main__':
unittest.main()