Files
weibo_signin/backend/tests/conftest.py

87 lines
2.5 KiB
Python
Raw Normal View History

2026-03-09 14:05:00 +08:00
"""
Shared test fixtures for Weibo-HotSign backend tests.
Uses SQLite in-memory for database tests and a simple dict-based
fake Redis for refresh-token tests, so no external services are needed.
"""
import asyncio
import sys
import os
from typing import AsyncGenerator
import pytest
import pytest_asyncio
from sqlalchemy.ext.asyncio import AsyncSession, create_async_engine
from sqlalchemy.orm import sessionmaker
# Ensure backend/ is on sys.path so `shared` and `app` imports work
sys.path.insert(0, os.path.join(os.path.dirname(__file__), ".."))
# --------------- override shared settings BEFORE any app import ---------------
os.environ["DATABASE_URL"] = "sqlite+aiosqlite://"
os.environ["REDIS_URL"] = "redis://localhost:6379/0"
os.environ["JWT_SECRET_KEY"] = "test-secret-key"
os.environ["COOKIE_ENCRYPTION_KEY"] = "test-cookie-key"
# Create the test engine BEFORE importing shared.models so we can swap it in
TEST_ENGINE = create_async_engine("sqlite+aiosqlite://", echo=False)
TestSessionLocal = sessionmaker(TEST_ENGINE, class_=AsyncSession, expire_on_commit=False)
# Now patch shared.models.base module-level objects before they get used
import shared.models.base as _base_mod # noqa: E402
_base_mod.engine = TEST_ENGINE
_base_mod.AsyncSessionLocal = TestSessionLocal
from shared.models.base import Base # noqa: E402
from shared.models import User # noqa: E402
@pytest.fixture(scope="session")
def event_loop():
"""Create a single event loop for the whole test session."""
loop = asyncio.new_event_loop()
yield loop
loop.close()
@pytest_asyncio.fixture(autouse=True)
async def setup_db():
"""Create all tables before each test, drop after."""
async with TEST_ENGINE.begin() as conn:
await conn.run_sync(Base.metadata.create_all)
yield
async with TEST_ENGINE.begin() as conn:
await conn.run_sync(Base.metadata.drop_all)
@pytest_asyncio.fixture
async def db_session() -> AsyncGenerator[AsyncSession, None]:
"""Yield a fresh async DB session."""
async with TestSessionLocal() as session:
yield session
# --------------- Fake Redis for refresh-token tests ---------------
class FakeRedis:
"""Minimal async Redis stand-in backed by a plain dict."""
def __init__(self):
self._store: dict[str, str] = {}
async def setex(self, key: str, ttl: int, value: str):
self._store[key] = value
async def get(self, key: str):
return self._store.get(key)
async def delete(self, key: str):
self._store.pop(key, None)
@pytest.fixture
def fake_redis():
return FakeRedis()