Skip to content

Commit 40c123e

Browse files
committed
fix e2e tests
Signed-off-by: Madhav Kandukuri <[email protected]>
1 parent be4dd21 commit 40c123e

File tree

3 files changed

+71
-66
lines changed

3 files changed

+71
-66
lines changed

tests/conftest.py

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,15 @@
1010
# Standard
1111
import asyncio
1212
import os
13+
import tempfile
1314
from unittest.mock import AsyncMock, patch
1415

1516
# Third-Party
17+
from _pytest.monkeypatch import MonkeyPatch
1618
import pytest
1719
from sqlalchemy import create_engine
1820
from sqlalchemy.orm import sessionmaker
21+
from sqlalchemy.pool import StaticPool
1922

2023
# First-Party
2124
from mcpgateway.config import Settings
@@ -107,3 +110,57 @@ def mock_websocket():
107110
# import mcpgateway.translate as translate
108111
# translate._run_stdio_to_sse = AsyncMock(return_value=None)
109112
# translate._run_sse_to_stdio = AsyncMock(return_value=None)
113+
114+
115+
@pytest.fixture(scope="module") # one DB per test module is usually fine
116+
def app_with_temp_db():
117+
"""Return a FastAPI app wired to a fresh SQLite database."""
118+
mp = MonkeyPatch()
119+
120+
# 1) create temp SQLite file
121+
fd, path = tempfile.mkstemp(suffix=".db")
122+
url = f"sqlite:///{path}"
123+
124+
# 2) patch settings
125+
# First-Party
126+
from mcpgateway.config import settings
127+
128+
mp.setattr(settings, "database_url", url, raising=False)
129+
130+
# First-Party
131+
import mcpgateway.db as db_mod
132+
133+
engine = create_engine(url, connect_args={"check_same_thread": False}, poolclass=StaticPool)
134+
TestSessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
135+
mp.setattr(db_mod, "engine", engine, raising=False)
136+
mp.setattr(db_mod, "SessionLocal", TestSessionLocal, raising=False)
137+
138+
# 4) patch the already‑imported main module **without reloading**
139+
# First-Party
140+
import mcpgateway.main as main_mod
141+
142+
mp.setattr(main_mod, "SessionLocal", TestSessionLocal, raising=False)
143+
# (patch engine too if your code references it)
144+
mp.setattr(main_mod, "engine", engine, raising=False)
145+
146+
# 4) create schema
147+
db_mod.Base.metadata.create_all(bind=engine)
148+
149+
# 5) reload main so routers, deps pick up new SessionLocal
150+
# if "mcpgateway.main" in sys.modules:
151+
# import importlib
152+
153+
# importlib.reload(sys.modules["mcpgateway.main"])
154+
# else:
155+
# import mcpgateway.main # noqa: F401
156+
157+
# First-Party
158+
from mcpgateway.main import app
159+
160+
yield app
161+
162+
# 6) teardown
163+
mp.undo()
164+
engine.dispose()
165+
os.close(fd)
166+
os.unlink(path)

tests/e2e/test_admin_apis.py

Lines changed: 11 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -35,24 +35,18 @@
3535
os.environ["MCPGATEWAY_UI_ENABLED"] = "true"
3636

3737
# Standard
38-
import tempfile
39-
from typing import AsyncGenerator
38+
import logging
4039
from unittest.mock import patch
4140
from urllib.parse import quote
4241
import uuid
43-
import logging
4442

4543
# Third-Party
4644
from httpx import AsyncClient
4745
import pytest
4846
import pytest_asyncio
49-
from sqlalchemy import create_engine
50-
from sqlalchemy.orm import sessionmaker
51-
from sqlalchemy.pool import StaticPool
5247

53-
# First-Party
54-
from mcpgateway.db import Base
55-
from mcpgateway.main import app, get_db
48+
# from mcpgateway.db import Base
49+
# from mcpgateway.main import app, get_db
5650

5751

5852
# Configure logging for debugging
@@ -77,72 +71,23 @@ def setup_logging():
7771
# Fixtures
7872
# -------------------------
7973
@pytest_asyncio.fixture
80-
async def temp_db():
81-
"""
82-
Create a temporary SQLite database for testing.
83-
84-
This fixture creates a fresh database for each test, ensuring complete
85-
isolation between tests. The database is automatically cleaned up after
86-
the test completes.
87-
"""
88-
# Create temporary file for SQLite database
89-
db_fd, db_path = tempfile.mkstemp(suffix=".db")
90-
91-
# Create engine with SQLite
92-
engine = create_engine(
93-
f"sqlite:///{db_path}",
94-
connect_args={"check_same_thread": False},
95-
poolclass=StaticPool,
96-
)
97-
98-
# Log the database path for debugging
99-
logging.debug(f"Using temporary database at: {db_path}")
100-
101-
# Create all tables
102-
Base.metadata.create_all(bind=engine)
103-
104-
# Create session factory
105-
TestSessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
106-
107-
# Override the get_db dependency
108-
def override_get_db():
109-
db = TestSessionLocal()
110-
try:
111-
yield db
112-
finally:
113-
db.close()
114-
115-
app.dependency_overrides[get_db] = override_get_db
116-
117-
# Override authentication for all tests
74+
async def client(app_with_temp_db):
11875
# First-Party
11976
from mcpgateway.utils.verify_credentials import require_auth, require_basic_auth
12077

121-
def override_auth():
122-
return TEST_USER
123-
124-
app.dependency_overrides[require_auth] = override_auth
125-
app.dependency_overrides[require_basic_auth] = override_auth
126-
127-
yield engine
78+
app_with_temp_db.dependency_overrides[require_auth] = lambda: TEST_USER
79+
app_with_temp_db.dependency_overrides[require_basic_auth] = lambda: TEST_USER
12880

129-
# Cleanup
130-
logging.debug("Cleaning up temporary database and overrides.")
131-
app.dependency_overrides.clear()
132-
os.close(db_fd)
133-
os.unlink(db_path)
134-
135-
136-
@pytest_asyncio.fixture
137-
async def client(temp_db) -> AsyncGenerator[AsyncClient, None]:
138-
"""Create an async test client with the test database."""
13981
# Third-Party
14082
from httpx import ASGITransport, AsyncClient
14183

142-
transport = ASGITransport(app=app)
84+
transport = ASGITransport(app=app_with_temp_db)
14385
async with AsyncClient(transport=transport, base_url="http://test") as ac:
14486
yield ac
14587

88+
app_with_temp_db.dependency_overrides.pop(require_auth, None)
89+
app_with_temp_db.dependency_overrides.pop(require_basic_auth, None)
90+
14691

14792
@pytest_asyncio.fixture
14893
async def mock_settings():
@@ -351,7 +296,7 @@ async def test_admin_tool_name_conflict(self, client: AsyncClient, mock_settings
351296
class TestAdminResourceAPIs:
352297
"""Test admin resource management endpoints."""
353298

354-
async def test_admin_add_resource(self, client: AsyncClient, mock_settings, temp_db):
299+
async def test_admin_add_resource(self, client: AsyncClient, mock_settings):
355300
"""Test adding a resource via the admin UI with new logic."""
356301
# Define valid form data
357302
valid_form_data = {

tests/security/test_rpc_api.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
import json
1717
import os
1818
import sys
19+
20+
# Third-Party
1921
import pytest
2022

2123
try:
@@ -25,6 +27,7 @@
2527
print("Please install requests: pip install requests")
2628
sys.exit(1)
2729

30+
2831
@pytest.mark.skip(reason="Disabled temporarily as this requires a live MCP Gateway instance")
2932
def test_rpc_vulnerability():
3033
"""Test the RPC endpoint with malicious method names."""

0 commit comments

Comments
 (0)