# ================================================================ # services/auth/tests/conftest.py # ================================================================ """ Simple pytest configuration for auth service with mock database """ import pytest import pytest_asyncio import uuid from typing import AsyncGenerator from unittest.mock import AsyncMock, Mock from sqlalchemy.ext.asyncio import AsyncSession, create_async_engine, async_sessionmaker from sqlalchemy.pool import StaticPool from fastapi.testclient import TestClient # Test database URL - using in-memory SQLite for simplicity TEST_DATABASE_URL = "sqlite+aiosqlite:///:memory:" # Create test engine test_engine = create_async_engine( TEST_DATABASE_URL, connect_args={"check_same_thread": False}, poolclass=StaticPool, echo=False ) # Create async session maker TestingSessionLocal = async_sessionmaker( test_engine, class_=AsyncSession, expire_on_commit=False ) @pytest_asyncio.fixture async def mock_db() -> AsyncGenerator[AsyncMock, None]: """Create a mock database session for testing""" mock_session = AsyncMock(spec=AsyncSession) # Configure common mock behaviors mock_session.commit = AsyncMock() mock_session.rollback = AsyncMock() mock_session.close = AsyncMock() mock_session.refresh = AsyncMock() mock_session.add = Mock() mock_session.execute = AsyncMock() mock_session.scalar = AsyncMock() mock_session.scalars = AsyncMock() yield mock_session @pytest_asyncio.fixture async def real_test_db() -> AsyncGenerator[AsyncSession, None]: """Create a real test database session (in-memory SQLite)""" # Import here to avoid circular imports from app.core.database import Base async with test_engine.begin() as conn: await conn.run_sync(Base.metadata.create_all) async with TestingSessionLocal() as session: yield session async with test_engine.begin() as conn: await conn.run_sync(Base.metadata.drop_all) @pytest.fixture def mock_redis(): """Create a mock Redis client""" mock_redis = AsyncMock() mock_redis.get = AsyncMock(return_value=None) mock_redis.set = AsyncMock(return_value=True) mock_redis.setex = AsyncMock(return_value=True) # Add setex method mock_redis.delete = AsyncMock(return_value=1) mock_redis.incr = AsyncMock(return_value=1) mock_redis.expire = AsyncMock(return_value=True) return mock_redis @pytest.fixture def test_client(): """Create a test client for the FastAPI app""" from app.main import app return TestClient(app) @pytest.fixture def test_tenant_id(): """Generate a test tenant ID""" return uuid.uuid4() @pytest.fixture def test_user_data(): """Generate test user data""" unique_id = uuid.uuid4().hex[:8] return { "email": f"test_{unique_id}@bakery.es", "password": "TestPassword123!", "full_name": f"Test User {unique_id}", "tenant_id": uuid.uuid4() } @pytest.fixture def test_user_create_data(): """Generate user creation data for database""" return { "id": uuid.uuid4(), "email": "test@bakery.es", "full_name": "Test User", "hashed_password": "$2b$12$LQv3c1yqBWVHxkd0LHAkCOYz6TtxMQJqhN8/LewDtmRhckC.wSqDa", # "password123" "is_active": True, "tenant_id": uuid.uuid4(), "created_at": "2024-01-01T00:00:00", "updated_at": "2024-01-01T00:00:00" } @pytest.fixture def mock_user(): """Create a mock user object""" mock_user = Mock() mock_user.id = uuid.uuid4() mock_user.email = "test@bakery.es" mock_user.full_name = "Test User" mock_user.is_active = True mock_user.is_verified = False mock_user.tenant_id = uuid.uuid4() mock_user.hashed_password = "$2b$12$LQv3c1yqBWVHxkd0LHAkCOYz6TtxMQJqhN8/LewDtmRhckC.wSqDa" mock_user.created_at = "2024-01-01T00:00:00" mock_user.updated_at = "2024-01-01T00:00:00" return mock_user @pytest.fixture def mock_tokens(): """Create mock JWT tokens""" return { "access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ", "refresh_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ", "token_type": "bearer" } @pytest.fixture def auth_headers(mock_tokens): """Create authorization headers for testing""" return {"Authorization": f"Bearer {mock_tokens['access_token']}"} def generate_random_user_data(prefix="test"): """Generate unique user data for testing""" unique_id = uuid.uuid4().hex[:8] return { "email": f"{prefix}_{unique_id}@bakery.es", "password": f"TestPassword{unique_id}!", "full_name": f"Test User {unique_id}" } # Pytest configuration def pytest_configure(config): """Configure pytest markers""" config.addinivalue_line("markers", "unit: Unit tests") config.addinivalue_line("markers", "integration: Integration tests") config.addinivalue_line("markers", "api: API endpoint tests") config.addinivalue_line("markers", "security: Security-related tests") config.addinivalue_line("markers", "slow: Slow-running tests") # Mock environment variables for testing @pytest.fixture(autouse=True) def mock_env_vars(monkeypatch): """Mock environment variables for testing""" monkeypatch.setenv("JWT_SECRET_KEY", "test-secret-key-for-testing") monkeypatch.setenv("JWT_ACCESS_TOKEN_EXPIRE_MINUTES", "30") monkeypatch.setenv("JWT_REFRESH_TOKEN_EXPIRE_DAYS", "7") monkeypatch.setenv("MAX_LOGIN_ATTEMPTS", "5") monkeypatch.setenv("LOCKOUT_DURATION_MINUTES", "30") monkeypatch.setenv("DATABASE_URL", TEST_DATABASE_URL) monkeypatch.setenv("REDIS_URL", "redis://localhost:6379/1") monkeypatch.setenv("RABBITMQ_URL", "amqp://guest:guest@localhost:5672/")