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
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:
220
services/service-adapters/tests/test_status_checker.py
Normal file
220
services/service-adapters/tests/test_status_checker.py
Normal 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()
|
||||
Reference in New Issue
Block a user