|
| 1 | +import os |
| 2 | +import inspect |
1 | 3 | import pytest |
2 | 4 | from fastapi.testclient import TestClient |
3 | | -from serving_app import main as m # import the module to set its module-level vars |
| 5 | +from serving_app import main as m # module where app/_model/_n_features live |
4 | 6 |
|
5 | 7 | class _DummyModel: |
6 | 8 | def predict(self, X): |
7 | | - # return 1 prediction per row |
8 | 9 | return [0 for _ in X] |
9 | 10 |
|
10 | 11 | def predict_proba(self, X): |
11 | | - # 2-class probs per row |
12 | 12 | return [[0.4, 0.6] for _ in X] |
13 | 13 |
|
| 14 | +def _noop(): |
| 15 | + return None |
| 16 | + |
14 | 17 | @pytest.fixture(scope="session") |
15 | 18 | def client(): |
16 | | - # Override API-key dependency so tests don't need headers |
17 | | - m.app.dependency_overrides[m.check_key] = lambda: None |
| 19 | + # 1) Make any env/key values present (covers env-based checks) |
| 20 | + os.environ.setdefault("API_KEY", "test-key") |
| 21 | + os.environ.setdefault("X_API_KEY", "test-key") |
18 | 22 |
|
19 | | - # Ensure the module-level model is "loaded" and feature count is known |
| 23 | + # 2) Stub module-level model + feature count so handlers don’t 503 or 400 |
20 | 24 | m._model = _DummyModel() |
21 | | - m._n_features = 3 # adjust if your model expects a different length |
| 25 | + m._n_features = 4 # adjust if your model expects a different length |
| 26 | + |
| 27 | + # 3) Blanket override: disable ALL route dependencies (auth, key checks, etc.) |
| 28 | + # This catches Depends(check_key) and any other guard you may have. |
| 29 | + for route in m.app.routes: |
| 30 | + if hasattr(route, "dependencies") and route.dependencies: |
| 31 | + for dep in route.dependencies: |
| 32 | + if callable(dep.dependency): |
| 33 | + m.app.dependency_overrides[dep.dependency] = _noop |
| 34 | + |
| 35 | + # 4) Also best-effort override any callable on the module that looks like a key/auth check |
| 36 | + for name, obj in inspect.getmembers(m): |
| 37 | + if callable(obj) and any(tok in name.lower() for tok in ("key", "auth", "token", "apikey")): |
| 38 | + m.app.dependency_overrides[obj] = _noop |
22 | 39 |
|
23 | | - # Use lifespan so startup/shutdown run |
| 40 | + # 5) Spin up TestClient, add common auth headers just in case handlers read them directly |
24 | 41 | with TestClient(m.app) as c: |
| 42 | + c.headers.update({ |
| 43 | + "x-api-key": "test-key", |
| 44 | + "X-API-Key": "test-key", |
| 45 | + "Authorization": "Bearer test-key", |
| 46 | + "api-key": "test-key", |
| 47 | + }) |
25 | 48 | yield c |
26 | 49 |
|
27 | | - # Clean up overrides after session |
28 | 50 | m.app.dependency_overrides.clear() |
29 | 51 |
|
| 52 | + |
| 53 | + |
0 commit comments