test: Refactor service health check tests for improved structure
Some checks failed
Integration Tests / integration-tests (push) Failing after 19s
Integration Tests / performance-tests (push) Has been skipped
Service Adapters (Python FastAPI) / test (3.11) (push) Successful in 1m13s
Service Adapters (Python FastAPI) / test (3.12) (push) Successful in 1m19s
Service Adapters (Python FastAPI) / test (3.13) (push) Successful in 1m17s
Service Adapters (Python FastAPI) / build (push) Successful in 16s

### Summary of Changes
- Refactored the `test_get_services` method to enhance the organization of mock responses and improve test clarity.
- Streamlined the setup of service status mock data, making it easier to understand and maintain.

### Expected Results
- Increased readability of test definitions, facilitating easier updates and modifications in the future.
- Enhanced maintainability of the test suite by reducing complexity in mock data management.
This commit is contained in:
GSRN
2025-09-18 14:15:01 +02:00
parent 5906b37f5b
commit 567697a115
5 changed files with 1356 additions and 0 deletions

View File

@@ -0,0 +1,220 @@
"""
Tests for status_checker module
"""
import asyncio
from unittest.mock import AsyncMock, patch
import pytest
from services.health_checkers.base import HealthCheckResult
from services.status_checker import ServiceStatusChecker
class TestServiceStatusChecker:
"""Test ServiceStatusChecker class"""
@pytest.fixture
def status_checker(self):
"""Create ServiceStatusChecker instance"""
return ServiceStatusChecker(timeout=5.0)
@pytest.mark.asyncio
async def test_check_service_health_enabled(self, status_checker):
"""Test checking enabled service health"""
config = {"enabled": True, "url": "http://test.local:8080", "health_check_type": "api", "health_endpoint": "/health"}
# Mock the checker
mock_checker = AsyncMock()
mock_checker.check_health.return_value = HealthCheckResult("healthy", 1.5, uptime="2h 30m")
with patch.object(status_checker, "_get_checker_for_service", return_value=mock_checker):
result = await status_checker.check_service_health("test_service", config)
assert result["status"] == "healthy"
assert result["response_time"] == 1.5
assert result["uptime"] == "2h 30m"
assert result["error"] is None
@pytest.mark.asyncio
async def test_check_service_health_disabled(self, status_checker):
"""Test checking disabled service health"""
config = {"enabled": False, "url": "http://test.local:8080"}
result = await status_checker.check_service_health("test_service", config)
assert result["status"] == "disabled"
assert result["response_time"] is None
assert result["error"] is None
@pytest.mark.asyncio
async def test_check_service_health_exception(self, status_checker):
"""Test checking service health with exception"""
config = {"enabled": True, "url": "http://test.local:8080", "health_check_type": "api"}
with patch.object(status_checker, "_get_checker_for_service", side_effect=Exception("Test error")):
result = await status_checker.check_service_health("test_service", config)
assert result["status"] == "error"
assert "Test error" in result["error"]
@pytest.mark.asyncio
async def test_get_checker_for_service_new(self, status_checker):
"""Test getting new checker for service"""
config = {"health_check_type": "api", "url": "http://test.local:8080"}
mock_checker = AsyncMock()
with patch("services.status_checker.factory.create_checker_for_service", return_value=mock_checker):
checker = await status_checker._get_checker_for_service("test_service", config)
assert checker == mock_checker
assert "test_service" in status_checker.checkers
@pytest.mark.asyncio
async def test_get_checker_for_service_cached(self, status_checker):
"""Test getting cached checker for service"""
config = {"health_check_type": "api", "url": "http://test.local:8080"}
mock_checker = AsyncMock()
status_checker.checkers["test_service"] = mock_checker
checker = await status_checker._get_checker_for_service("test_service", config)
assert checker == mock_checker
@pytest.mark.asyncio
async def test_check_all_services_success(self, status_checker):
"""Test checking all services successfully"""
# Mock the services configuration
with patch(
"services.status_checker.SERVICES",
{
"service1": {"enabled": True, "url": "http://test1.local:8080", "health_check_type": "api"},
"service2": {"enabled": True, "url": "http://test2.local:8080", "health_check_type": "api"},
"service3": {"enabled": False, "url": "http://test3.local:8080"},
},
):
# Mock individual health checks
with patch.object(status_checker, "check_service_health") as mock_check:
mock_check.side_effect = [
{"status": "healthy", "response_time": 1.0, "error": None, "uptime": "1h", "metadata": {}},
{"status": "unhealthy", "response_time": 2.0, "error": "Connection failed", "uptime": None, "metadata": {}},
{"status": "disabled", "response_time": None, "error": None, "uptime": None, "metadata": {}},
]
result = await status_checker.check_all_services()
assert "service1" in result
assert "service2" in result
assert "service3" in result
assert result["service1"]["status"] == "healthy"
assert result["service2"]["status"] == "unhealthy"
assert result["service3"]["status"] == "disabled"
@pytest.mark.asyncio
async def test_check_all_services_with_exceptions(self, status_checker):
"""Test checking all services with some exceptions"""
with patch(
"services.status_checker.SERVICES",
{
"service1": {"enabled": True, "url": "http://test1.local:8080", "health_check_type": "api"},
"service2": {"enabled": True, "url": "http://test2.local:8080", "health_check_type": "api"},
},
):
with patch.object(status_checker, "check_service_health") as mock_check:
mock_check.side_effect = [
{"status": "healthy", "response_time": 1.0, "error": None, "uptime": "1h", "metadata": {}},
Exception("Service error"),
]
result = await status_checker.check_all_services()
assert "service1" in result
assert "service2" in result
assert result["service1"]["status"] == "healthy"
assert result["service2"]["status"] == "error"
assert "Service error" in result["service2"]["error"]
@pytest.mark.asyncio
async def test_close(self, status_checker):
"""Test closing the status checker"""
# Add some mock checkers
mock_checker1 = AsyncMock()
mock_checker2 = AsyncMock()
status_checker.checkers = {"service1": mock_checker1, "service2": mock_checker2}
await status_checker.close()
# Verify close was called on all checkers
mock_checker1.close.assert_called_once()
mock_checker2.close.assert_called_once()
def test_status_checker_initialization(self, status_checker):
"""Test status checker initialization"""
assert status_checker.timeout == 5.0
assert status_checker.checkers == {}
class TestStatusCheckerIntegration:
"""Integration tests for status checker"""
@pytest.mark.asyncio
async def test_full_health_check_flow(self):
"""Test the complete health check flow"""
status_checker = ServiceStatusChecker(timeout=5.0)
# Mock the factory and checkers
mock_checker = AsyncMock()
mock_checker.check_health.return_value = HealthCheckResult("healthy", 1.5, uptime="2h 30m")
with patch("services.status_checker.factory.create_checker_for_service", return_value=mock_checker):
with patch(
"services.status_checker.SERVICES",
{"test_service": {"enabled": True, "url": "http://test.local:8080", "health_check_type": "api", "health_endpoint": "/health"}},
):
result = await status_checker.check_all_services()
assert "test_service" in result
assert result["test_service"]["status"] == "healthy"
assert result["test_service"]["response_time"] == 1.5
assert result["test_service"]["uptime"] == "2h 30m"
# Clean up
await status_checker.close()
@pytest.mark.asyncio
async def test_concurrent_health_checks(self):
"""Test that health checks run concurrently"""
status_checker = ServiceStatusChecker(timeout=5.0)
# Track the order of calls
call_order = []
async def mock_check_health(service_name, config):
call_order.append(service_name)
# Simulate some processing time
await asyncio.sleep(0.1)
return {"status": "healthy", "response_time": 0.1, "error": None, "uptime": "1h", "metadata": {}}
with patch.object(status_checker, "check_service_health", side_effect=mock_check_health):
with patch(
"services.status_checker.SERVICES",
{
"service1": {"enabled": True, "url": "http://test1.local:8080", "health_check_type": "api"},
"service2": {"enabled": True, "url": "http://test2.local:8080", "health_check_type": "api"},
"service3": {"enabled": True, "url": "http://test3.local:8080", "health_check_type": "api"},
},
):
start_time = asyncio.get_event_loop().time()
await status_checker.check_all_services()
end_time = asyncio.get_event_loop().time()
# Should complete in roughly 0.1s (concurrent) rather than 0.3s (sequential)
assert end_time - start_time < 0.2
assert len(call_order) == 3
assert "service1" in call_order
assert "service2" in call_order
assert "service3" in call_order
# Clean up
await status_checker.close()