Add tests for health endpoint
This commit is contained in:
parent
6c07d47b1b
commit
49ef7997a2
7
.vscode/settings.json
vendored
Normal file
7
.vscode/settings.json
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
{
|
||||
"python.testing.pytestArgs": [
|
||||
"tests"
|
||||
],
|
||||
"python.testing.unittestEnabled": false,
|
||||
"python.testing.pytestEnabled": true
|
||||
}
|
||||
2
.vscode/tasks.json
vendored
2
.vscode/tasks.json
vendored
@ -6,7 +6,7 @@
|
||||
{
|
||||
"label": "Run Mypy",
|
||||
"type": "shell",
|
||||
"command": "uv run mypy .",
|
||||
"command": "uv run mypy . --no-incremental",
|
||||
"problemMatcher": [
|
||||
"$python"
|
||||
]
|
||||
|
||||
@ -25,9 +25,10 @@ class Settings(BaseSettings):
|
||||
dd_env: str = Field(default="development", alias="DD_ENV")
|
||||
dd_version: str = Field(default="1.0.0", alias="DD_VERSION")
|
||||
|
||||
class Config:
|
||||
env_file = ".env"
|
||||
case_sensitive = False
|
||||
model_config = {
|
||||
"env_file": ".env",
|
||||
"case_sensitive": False
|
||||
}
|
||||
|
||||
|
||||
settings = Settings() # type:ignore[call-arg]
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
from typing import Callable
|
||||
from typing import Callable, Any
|
||||
|
||||
from fastapi import Request, Response
|
||||
from slowapi import Limiter, _rate_limit_exceeded_handler
|
||||
@ -15,7 +15,7 @@ logger = get_logger(__name__)
|
||||
limiter = Limiter(key_func=get_remote_address)
|
||||
|
||||
|
||||
async def logging_middleware(request: Request, call_next: Callable) -> Response:
|
||||
async def logging_middleware(request: Request, call_next: Callable[[Request], Any]) -> Any:
|
||||
"""Log all requests and responses."""
|
||||
logger.debug(
|
||||
"Request received",
|
||||
|
||||
@ -2,8 +2,10 @@
|
||||
from fastapi import APIRouter
|
||||
|
||||
from app.database import DatabaseService
|
||||
from app.logging import get_logger
|
||||
|
||||
router = APIRouter()
|
||||
logger = get_logger(__name__)
|
||||
|
||||
|
||||
@router.get("/health-check")
|
||||
@ -11,7 +13,11 @@ async def health_check() -> dict[str, str]:
|
||||
"""Comprehensive health check endpoint."""
|
||||
|
||||
# Check database connectivity
|
||||
db_healthy = DatabaseService.health_check()
|
||||
try:
|
||||
db_healthy = DatabaseService.health_check()
|
||||
except Exception as e:
|
||||
logger.error("Database health check failed", exc_info=e)
|
||||
db_healthy = False
|
||||
|
||||
status = "healthy" if db_healthy else "unhealthy"
|
||||
|
||||
|
||||
@ -37,6 +37,7 @@ strict = true
|
||||
warn_return_any = true
|
||||
warn_unused_configs = true
|
||||
disallow_untyped_defs = true
|
||||
exclude = ["tests"]
|
||||
|
||||
[tool.pylint.messages_control]
|
||||
max-line-length = 88
|
||||
@ -48,15 +49,17 @@ multi_line_output = 3
|
||||
line_length = 88
|
||||
|
||||
[tool.pytest.ini_options]
|
||||
asyncio_mode = "auto"
|
||||
pythonpath = ["."]
|
||||
testpaths = ["tests"]
|
||||
|
||||
[dependency-groups]
|
||||
dev = [
|
||||
"autoflake>=2.3.1",
|
||||
"autopep8>=2.3.2",
|
||||
"httpx>=0.28.1",
|
||||
"isort>=7.0.0",
|
||||
"mypy>=1.19.1",
|
||||
"pylint-pydantic>=0.4.1",
|
||||
"pylint[pydantic]>=4.0.4",
|
||||
"pytest[coverage]>=9.0.2",
|
||||
]
|
||||
|
||||
61
tests/test_health.py
Normal file
61
tests/test_health.py
Normal file
@ -0,0 +1,61 @@
|
||||
"""Tests for health check endpoints."""
|
||||
import pytest
|
||||
from fastapi.testclient import TestClient
|
||||
from unittest.mock import patch
|
||||
|
||||
from main import create_app
|
||||
|
||||
|
||||
class TestHealthCheck:
|
||||
"""Test cases for health check endpoint."""
|
||||
|
||||
@pytest.fixture
|
||||
def client(self) -> TestClient:
|
||||
"""Create test client."""
|
||||
app = create_app()
|
||||
return TestClient(app)
|
||||
|
||||
@patch('app.database.DatabaseService.health_check')
|
||||
def test_health_check_database_connected(self, mock_db_health, client) -> None:
|
||||
"""Test health check when database is connected."""
|
||||
# Mock database as healthy
|
||||
mock_db_health.return_value = True
|
||||
|
||||
response = client.get("/health-check")
|
||||
|
||||
assert response.status_code == 200
|
||||
data = response.json()
|
||||
assert data["status"] == "healthy"
|
||||
assert data["service"] == "loapi"
|
||||
assert data["database"] == "connected"
|
||||
mock_db_health.assert_called_once()
|
||||
|
||||
@patch('app.database.DatabaseService.health_check')
|
||||
def test_health_check_database_disconnected(self, mock_db_health, client):
|
||||
"""Test health check when database is disconnected."""
|
||||
# Mock database as unhealthy
|
||||
mock_db_health.return_value = False
|
||||
|
||||
response = client.get("/health-check")
|
||||
|
||||
assert response.status_code == 200
|
||||
data = response.json()
|
||||
assert data["status"] == "unhealthy"
|
||||
assert data["service"] == "loapi"
|
||||
assert data["database"] == "disconnected"
|
||||
mock_db_health.assert_called_once()
|
||||
|
||||
@patch('app.database.DatabaseService.health_check')
|
||||
def test_health_check_database_exception(self, mock_db_health, client):
|
||||
"""Test health check when database check raises exception."""
|
||||
# Mock database health check to raise exception
|
||||
mock_db_health.side_effect = Exception("Database connection failed")
|
||||
|
||||
response = client.get("/health-check")
|
||||
|
||||
assert response.status_code == 200
|
||||
data = response.json()
|
||||
assert data["status"] == "unhealthy"
|
||||
assert data["service"] == "loapi"
|
||||
assert data["database"] == "disconnected"
|
||||
mock_db_health.assert_called_once()
|
||||
4
uv.lock
generated
4
uv.lock
generated
@ -715,10 +715,12 @@ dev = [
|
||||
dev = [
|
||||
{ name = "autoflake" },
|
||||
{ name = "autopep8" },
|
||||
{ name = "httpx" },
|
||||
{ name = "isort" },
|
||||
{ name = "mypy" },
|
||||
{ name = "pylint" },
|
||||
{ name = "pylint-pydantic" },
|
||||
{ name = "pytest" },
|
||||
]
|
||||
|
||||
[package.metadata]
|
||||
@ -750,10 +752,12 @@ provides-extras = ["dev"]
|
||||
dev = [
|
||||
{ name = "autoflake", specifier = ">=2.3.1" },
|
||||
{ name = "autopep8", specifier = ">=2.3.2" },
|
||||
{ name = "httpx", specifier = ">=0.28.1" },
|
||||
{ name = "isort", specifier = ">=7.0.0" },
|
||||
{ name = "mypy", specifier = ">=1.19.1" },
|
||||
{ name = "pylint", extras = ["pydantic"], specifier = ">=4.0.4" },
|
||||
{ name = "pylint-pydantic", specifier = ">=0.4.1" },
|
||||
{ name = "pytest", extras = ["coverage"], specifier = ">=9.0.2" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user