import pytest from fastapi.testclient import TestClient from sqlalchemy import create_engine, inspect from sqlalchemy.orm import sessionmaker from database.database import Base, get_db_session # Keep get_db_session for dependency override from fastapi import FastAPI from database import database as db # Import the database module directly @pytest.fixture(scope="function") def setup_db(monkeypatch): print("\n--- setup_db fixture started ---") # Use in-memory SQLite for tests test_db_url = "sqlite:///:memory:" monkeypatch.setenv("DATABASE_URL", test_db_url) # Monkeypatch the global engine and SessionLocal in the database module engine = create_engine(test_db_url, connect_args={"check_same_thread": False}) connection = engine.connect() # Begin a transaction and bind the session to it transaction = connection.begin() # Monkeypatch the global engine and SessionLocal in the database module monkeypatch.setattr(db, 'engine', engine) SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=connection) # Bind to the connection monkeypatch.setattr(db, 'SessionLocal', SessionLocal) from database.models import Base as ModelsBase # Renamed to avoid conflict with imported Base # Create all tables within the same connection ModelsBase.metadata.create_all(bind=connection) # Use the connection here # Verify table creation within setup_db inspector = inspect(connection) # Use the connection here if inspector.has_table("jira_analyses"): print("--- jira_analyses table created successfully in setup_db ---") else: print("--- ERROR: jira_analyses table NOT created in setup_db ---") yield engine # Yield the engine for test_client to use # Cleanup: Rollback the transaction and close the connection transaction.rollback() # Rollback to clean up data connection.close() print("--- setup_db fixture finished ---") @pytest.fixture def mock_full_jira_payload(setup_db): mock_data = { "issueKey": "PROJ-123", "summary": "Test Issue", "description": "Test Description", "comment": "Test Comment", "labels": ["test"], "status": "open", "assignee": "Tester", "updated": "2025-07-13T12:00:00Z" } return mock_data @pytest.fixture(scope="function") def test_client(setup_db, monkeypatch): print("\n--- test_client fixture started ---") # Prevent signal handling and lifespan initialization in tests monkeypatch.setattr("jira_webhook_llm.handle_shutdown_signal", lambda *args: None) monkeypatch.setattr("jira_webhook_llm.lifespan", lambda app: None) # Create a test app instance without lifespan app = FastAPI() # Import and include routers manually from webhooks.handlers import webhook_router from api.handlers import router as api_router app.include_router(webhook_router) app.include_router(api_router) # Override the get_db_session dependency to use the test database # This will now correctly use the monkeypatched SessionLocal from database.database def override_get_db_session(): db_session = db.SessionLocal() # Use the monkeypatched SessionLocal try: yield db_session finally: db_session.close() app.dependency_overrides[get_db_session] = override_get_db_session # Verify tables exist before running tests # Verify tables exist before running tests using the monkeypatched engine inspector = inspect(db.engine) # This will now inspect the engine bound to the single connection if inspector.has_table("jira_analyses"): print("--- jira_analyses table exists in test_client setup ---") else: print("--- ERROR: jira_analyses table NOT found in test_client setup ---") assert inspector.has_table("jira_analyses"), "Test tables not created" with TestClient(app) as client: yield client # Clean up dependency override app.dependency_overrides.clear() print("--- test_client fixture finished ---") @pytest.fixture def mock_jira_payload(): return { "issueKey": "TEST-123", "summary": "Test Issue", "description": "Test Description", "comment": "Test Comment", "labels": ["test"], "status": "Open", "assignee": "Tester", "updated": "2025-07-13T12:00:00Z" } # return { # "issueKey": "TEST-123", # "summary": "Test Issue", # "description": "Test Description", # "comment": "Test Comment", # "labels": ["test"], # "status": "Open", # "assignee": "Tester", # "updated": "2025-07-13T12:00:00Z" # }