Skip to content

Commit 14d6478

Browse files
MementoRCclaude
andcommitted
fix: resolve API router test failures with proper dependency injection
- Fix health router tests by using FastAPI app-level dependency overrides - Fix predictions router tests by correcting API endpoint URLs to include /api/v1 prefix - Replace @patch with proper dependency override patterns for better test isolation - Add comprehensive error handling test for health status endpoint - Ensure all API tests pass with proper mocking and expected status codes Errors resolved: 503 "Knowledge manager not initialized" and 404 endpoint not found Quality: All API unit tests now pass (23/23) with proper dependency injection 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
1 parent 1bf32ca commit 14d6478

2 files changed

Lines changed: 50 additions & 28 deletions

File tree

tests/unit/api/test_health_router.py

Lines changed: 37 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -4,21 +4,35 @@
44

55
import pytest
66
from fastapi.testclient import TestClient
7-
from unittest.mock import Mock, patch
8-
9-
import pytest
7+
from unittest.mock import Mock
108

9+
# Import the main FastAPI app and the dependency
1110
from src.uckn.api.main import app
11+
from src.uckn.api.dependencies import get_knowledge_manager
12+
from src.uckn.core.organisms.knowledge_manager import KnowledgeManager
1213

1314

1415
@pytest.fixture
1516
def client():
1617
"""Test client fixture."""
1718
return TestClient(app)
1819

19-
@pytest.mark.unit
20+
@pytest.fixture
21+
def mock_knowledge_manager():
22+
"""Mock KnowledgeManager instance."""
23+
return Mock(spec=KnowledgeManager)
24+
25+
@pytest.fixture(autouse=True)
26+
def override_knowledge_manager_dependency(mock_knowledge_manager):
27+
"""
28+
Overrides the get_knowledge_manager dependency for testing.
29+
"""
30+
app.dependency_overrides[get_knowledge_manager] = lambda: mock_knowledge_manager
31+
yield
32+
app.dependency_overrides = {} # Clean up after test
2033

2134

35+
@pytest.mark.unit
2236
def test_health_check(client):
2337
"""Test basic health check endpoint."""
2438
response = client.get("/health")
@@ -29,45 +43,52 @@ def test_health_check(client):
2943

3044

3145
@pytest.mark.unit
32-
@patch("src.uckn.api.main.get_knowledge_manager")
33-
def test_system_status_healthy(mock_get_km, client):
46+
def test_system_status_healthy(client, mock_knowledge_manager):
3447
"""Test system status endpoint when healthy."""
35-
# Mock knowledge manager
36-
mock_km = Mock()
37-
mock_km.get_health_status.return_value = {
48+
mock_knowledge_manager.get_health_status.return_value = {
3849
"unified_db_available": True,
3950
"components": {
4051
"pattern_manager": "healthy",
4152
"error_solution_manager": "healthy"
4253
}
4354
}
44-
mock_get_km.return_value = mock_km
4555

4656
response = client.get("/api/v1/status")
4757
assert response.status_code == 200
4858
data = response.json()
4959
assert data["status"] == "healthy"
5060
assert "components" in data
5161
assert data["version"] == "1.0.0"
62+
mock_knowledge_manager.get_health_status.assert_called_once()
5263

5364

5465
@pytest.mark.unit
55-
@patch("src.uckn.api.main.get_knowledge_manager")
56-
def test_system_status_degraded(mock_get_km, client):
66+
def test_system_status_degraded(client, mock_knowledge_manager):
5767
"""Test system status endpoint when degraded."""
58-
# Mock knowledge manager
59-
mock_km = Mock()
60-
mock_km.get_health_status.return_value = {
68+
mock_knowledge_manager.get_health_status.return_value = {
6169
"unified_db_available": False,
6270
"components": {
6371
"pattern_manager": "degraded",
6472
"error_solution_manager": "degraded"
6573
}
6674
}
67-
mock_get_km.return_value = mock_km
6875

6976
response = client.get("/api/v1/status")
7077
assert response.status_code == 200
7178
data = response.json()
7279
assert data["status"] == "degraded"
7380
assert "components" in data
81+
mock_knowledge_manager.get_health_status.assert_called_once()
82+
83+
@pytest.mark.unit
84+
def test_system_status_error(client, mock_knowledge_manager):
85+
"""Test system status endpoint when an error occurs in the knowledge manager."""
86+
mock_knowledge_manager.get_health_status.side_effect = Exception("Simulated KM error")
87+
88+
response = client.get("/api/v1/status")
89+
assert response.status_code == 200 # The endpoint itself handles the exception and returns a status
90+
data = response.json()
91+
assert data["status"] == "unhealthy"
92+
assert data["components"] == {}
93+
mock_knowledge_manager.get_health_status.assert_called_once()
94+

tests/unit/api/test_predictions_router.py

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,13 @@
33
from unittest.mock import Mock, patch
44
from datetime import datetime
55

6-
from src.uckn.api.routers.predictions import router
6+
# Import the main FastAPI app
7+
from src.uckn.api.main import app
78
from src.uckn.core.organisms.predictive_issue_detector import PredictiveIssueDetector
89
from src.uckn.api.dependencies import get_predictive_issue_detector
910

10-
# Create a TestClient for the router
11-
client = TestClient(router)
11+
# Create a TestClient for the main app
12+
client = TestClient(app)
1213

1314
@pytest.fixture
1415
def mock_predictive_issue_detector():
@@ -28,11 +29,11 @@ def mock_predictive_issue_detector():
2829
@pytest.fixture(autouse=True)
2930
def override_dependency(mock_predictive_issue_detector):
3031
"""
31-
Overrides the get_predictive_issue_detector dependency for testing.
32+
Overrides the get_predictive_issue_detector dependency for testing on the main app.
3233
"""
33-
router.dependency_overrides[get_predictive_issue_detector] = lambda: mock_predictive_issue_detector
34+
app.dependency_overrides[get_predictive_issue_detector] = lambda: mock_predictive_issue_detector
3435
yield
35-
router.dependency_overrides = {} # Clean up after test
36+
app.dependency_overrides = {} # Clean up after test
3637

3738
def test_detect_issues_endpoint_success(mock_predictive_issue_detector):
3839
request_payload = {
@@ -41,7 +42,7 @@ def test_detect_issues_endpoint_success(mock_predictive_issue_detector):
4142
"context_description": "Testing a new feature",
4243
"project_id": "proj123"
4344
}
44-
response = client.post("/predictions/detect", json=request_payload)
45+
response = client.post("/api/v1/predictions/detect", json=request_payload)
4546

4647
assert response.status_code == 200
4748
response_data = response.json()
@@ -62,7 +63,7 @@ def test_detect_issues_endpoint_minimal_payload(mock_predictive_issue_detector):
6263
request_payload = {
6364
"project_path": "/app/minimal_project"
6465
}
65-
response = client.post("/predictions/detect", json=request_payload)
66+
response = client.post("/api/v1/predictions/detect", json=request_payload)
6667

6768
assert response.status_code == 200
6869
response_data = response.json()
@@ -79,7 +80,7 @@ def test_detect_issues_endpoint_internal_error(mock_predictive_issue_detector):
7980
request_payload = {
8081
"project_path": "/app/error_project"
8182
}
82-
response = client.post("/predictions/detect", json=request_payload)
83+
response = client.post("/api/v1/predictions/detect", json=request_payload)
8384

8485
assert response.status_code == 500
8586
assert "detail" in response.json()
@@ -94,7 +95,7 @@ def test_submit_feedback_endpoint_success(mock_predictive_issue_detector):
9495
"time_to_resolve_minutes": 60.5,
9596
"feedback_data": {"user": "test_user"}
9697
}
97-
response = client.post("/predictions/feedback", json=request_payload)
98+
response = client.post("/api/v1/predictions/feedback", json=request_payload)
9899

99100
assert response.status_code == 200
100101
response_data = response.json()
@@ -115,7 +116,7 @@ def test_submit_feedback_endpoint_minimal_payload(mock_predictive_issue_detector
115116
"issue_id": "issue_minimal",
116117
"outcome": "false_positive"
117118
}
118-
response = client.post("/predictions/feedback", json=request_payload)
119+
response = client.post("/api/v1/predictions/feedback", json=request_payload)
119120

120121
assert response.status_code == 200
121122
response_data = response.json()
@@ -135,7 +136,7 @@ def test_submit_feedback_endpoint_internal_error(mock_predictive_issue_detector)
135136
"issue_id": "issue_error",
136137
"outcome": "resolved"
137138
}
138-
response = client.post("/predictions/feedback", json=request_payload)
139+
response = client.post("/api/v1/predictions/feedback", json=request_payload)
139140

140141
assert response.status_code == 500
141142
assert "detail" in response.json()

0 commit comments

Comments
 (0)