Public Access
172 lines
5.7 KiB
Python
172 lines
5.7 KiB
Python
"""Unit tests for devx.utils.api.APIClient."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from unittest.mock import MagicMock, patch
|
|
|
|
import pytest
|
|
import requests
|
|
|
|
from devx.utils.api import APIClient
|
|
|
|
|
|
class TestAPIClient:
|
|
@patch("devx.utils.api.requests.request")
|
|
def test_get(self, mock_req):
|
|
mock_resp = MagicMock()
|
|
mock_resp.raise_for_status.return_value = None
|
|
mock_req.return_value = mock_resp
|
|
client = APIClient("https://api.example.com", {"Authorization": "Bearer token"})
|
|
result = client.get("/users")
|
|
assert result is mock_resp
|
|
mock_req.assert_called_once_with(
|
|
"GET",
|
|
"https://api.example.com/users",
|
|
headers={"Authorization": "Bearer token"},
|
|
timeout=30,
|
|
verify=True,
|
|
)
|
|
|
|
@patch("devx.utils.api.requests.request")
|
|
def test_post(self, mock_req):
|
|
mock_resp = MagicMock()
|
|
mock_resp.raise_for_status.return_value = None
|
|
mock_req.return_value = mock_resp
|
|
client = APIClient("https://api.example.com", {})
|
|
client.post("/users", json={"name": "alice"})
|
|
mock_req.assert_called_once_with(
|
|
"POST",
|
|
"https://api.example.com/users",
|
|
headers={},
|
|
timeout=30,
|
|
verify=True,
|
|
json={"name": "alice"},
|
|
)
|
|
|
|
@patch("devx.utils.api.requests.request")
|
|
def test_put(self, mock_req):
|
|
mock_resp = MagicMock()
|
|
mock_resp.raise_for_status.return_value = None
|
|
mock_req.return_value = mock_resp
|
|
client = APIClient("https://api.example.com", {})
|
|
client.put("/users/1", json={"name": "bob"})
|
|
mock_req.assert_called_once_with(
|
|
"PUT",
|
|
"https://api.example.com/users/1",
|
|
headers={},
|
|
timeout=30,
|
|
verify=True,
|
|
json={"name": "bob"},
|
|
)
|
|
|
|
@patch("devx.utils.api.requests.request")
|
|
def test_delete(self, mock_req):
|
|
mock_resp = MagicMock()
|
|
mock_resp.raise_for_status.return_value = None
|
|
mock_req.return_value = mock_resp
|
|
client = APIClient("https://api.example.com", {})
|
|
client.delete("/users/1")
|
|
mock_req.assert_called_once_with(
|
|
"DELETE",
|
|
"https://api.example.com/users/1",
|
|
headers={},
|
|
timeout=30,
|
|
verify=True,
|
|
)
|
|
|
|
@patch("devx.utils.api.requests.request")
|
|
def test_patch(self, mock_req):
|
|
mock_resp = MagicMock()
|
|
mock_resp.raise_for_status.return_value = None
|
|
mock_req.return_value = mock_resp
|
|
client = APIClient("https://api.example.com", {})
|
|
client.patch("/users/1", json={"name": "carol"})
|
|
mock_req.assert_called_once_with(
|
|
"PATCH",
|
|
"https://api.example.com/users/1",
|
|
headers={},
|
|
timeout=30,
|
|
verify=True,
|
|
json={"name": "carol"},
|
|
)
|
|
|
|
@patch("devx.utils.api.requests.request")
|
|
def test_auth_tuple(self, mock_req):
|
|
mock_resp = MagicMock()
|
|
mock_resp.raise_for_status.return_value = None
|
|
mock_req.return_value = mock_resp
|
|
client = APIClient("https://api.example.com", {}, auth=("admin", "pass"))
|
|
client.get("/data")
|
|
mock_req.assert_called_once_with(
|
|
"GET",
|
|
"https://api.example.com/data",
|
|
headers={},
|
|
timeout=30,
|
|
verify=True,
|
|
auth=("admin", "pass"),
|
|
)
|
|
|
|
@patch("devx.utils.api.requests.request")
|
|
def test_custom_timeout_and_verify(self, mock_req):
|
|
mock_resp = MagicMock()
|
|
mock_resp.raise_for_status.return_value = None
|
|
mock_req.return_value = mock_resp
|
|
client = APIClient("https://api.example.com", {}, timeout=60, verify=False)
|
|
client.get("/data")
|
|
mock_req.assert_called_once_with(
|
|
"GET",
|
|
"https://api.example.com/data",
|
|
headers={},
|
|
timeout=60,
|
|
verify=False,
|
|
)
|
|
|
|
@patch("devx.utils.api.requests.request")
|
|
def test_raises_on_error(self, mock_req):
|
|
mock_resp = MagicMock()
|
|
mock_resp.raise_for_status.side_effect = requests.HTTPError("500")
|
|
mock_req.return_value = mock_resp
|
|
client = APIClient("https://api.example.com", {})
|
|
with pytest.raises(requests.HTTPError):
|
|
client.get("/fail")
|
|
|
|
@patch("devx.utils.api.requests.request")
|
|
def test_strips_trailing_slash(self, mock_req):
|
|
mock_resp = MagicMock()
|
|
mock_resp.raise_for_status.return_value = None
|
|
mock_req.return_value = mock_resp
|
|
client = APIClient("https://api.example.com/", {})
|
|
client.get("/users")
|
|
mock_req.assert_called_once_with(
|
|
"GET",
|
|
"https://api.example.com/users",
|
|
headers={},
|
|
timeout=30,
|
|
verify=True,
|
|
)
|
|
|
|
@patch("devx.utils.api.requests.request")
|
|
def test_kwargs_override_defaults(self, mock_req):
|
|
mock_resp = MagicMock()
|
|
mock_resp.raise_for_status.return_value = None
|
|
mock_req.return_value = mock_resp
|
|
client = APIClient("https://api.example.com", {}, timeout=30)
|
|
client.get("/slow", timeout=120)
|
|
mock_req.assert_called_once_with(
|
|
"GET",
|
|
"https://api.example.com/slow",
|
|
headers={},
|
|
timeout=120,
|
|
verify=True,
|
|
)
|
|
|
|
@patch("devx.utils.api.requests.request")
|
|
def test_no_auth_when_not_set(self, mock_req):
|
|
mock_resp = MagicMock()
|
|
mock_resp.raise_for_status.return_value = None
|
|
mock_req.return_value = mock_resp
|
|
client = APIClient("https://api.example.com", {})
|
|
client.get("/data")
|
|
call_kwargs = mock_req.call_args.kwargs
|
|
assert "auth" not in call_kwargs
|