from datetime import datetime from unittest.mock import MagicMock import pytest from fastapi import status, HTTPException from fastapi.testclient import TestClient from mongomock.mongo_client import MongoClient from app.api.dependencies import get_auth_service, get_user_service, get_current_user from app.main import app # Assuming you have FastAPI app defined in app/main.py from app.models.auth import UserRole from app.models.types import PyObjectId from app.models.user import UserInDB from app.services.auth_service import AuthService from app.services.user_service import UserService @pytest.fixture def client(): return TestClient(app) @pytest.fixture def fake_user(): return UserInDB( _id=PyObjectId(), username="testuser", email="test@example.com", role=UserRole.USER, is_active=True, hashed_password="hashed-secret", created_at=datetime(2025, 1, 1), updated_at=datetime(2025, 1, 2), ) def override_auth_service(): mock = MagicMock(spec=AuthService) mock.verify_user_password.return_value = True mock.create_access_token.return_value = "fake-jwt-token" return mock def override_user_service(fake_user): mock = MagicMock(spec=UserService) mock.get_user_by_username.return_value = fake_user return mock def override_get_current_user(fake_user): def _override(): return fake_user return _override def override_get_database(): def _override(): client = MongoClient() db = client.test_database return db return _override # ---------------------- TESTS FOR /auth/login ---------------------- class TestLogin: def test_i_can_login_with_valid_credentials(self, client, fake_user): auth_service = override_auth_service() user_service = override_user_service(fake_user) client.app.dependency_overrides[get_auth_service] = lambda: auth_service client.app.dependency_overrides[get_user_service] = lambda: user_service response = client.post( "/auth/login", data={"username": "testuser", "password": "secret"}, ) assert response.status_code == status.HTTP_200_OK data = response.json() assert "access_token" in data assert data["user"]["username"] == "testuser" def test_i_cannot_login_with_invalid_username(self, client): auth_service = override_auth_service() user_service = MagicMock(spec=UserService) user_service.get_user_by_username.return_value = None client.app.dependency_overrides[get_auth_service] = lambda: auth_service client.app.dependency_overrides[get_user_service] = lambda: user_service response = client.post( "/auth/login", data={"username": "unknown", "password": "secret"}, ) assert response.status_code == status.HTTP_401_UNAUTHORIZED def test_i_cannot_login_with_inactive_user(self, client, fake_user): fake_user.is_active = False auth_service = override_auth_service() user_service = override_user_service(fake_user) client.app.dependency_overrides[get_auth_service] = lambda: auth_service client.app.dependency_overrides[get_user_service] = lambda: user_service response = client.post( "/auth/login", data={"username": "testuser", "password": "secret"}, ) assert response.status_code == status.HTTP_401_UNAUTHORIZED def test_i_cannot_login_with_wrong_password(self, client, fake_user): auth_service = override_auth_service() auth_service.verify_user_password.return_value = False user_service = override_user_service(fake_user) client.app.dependency_overrides[get_auth_service] = lambda: auth_service client.app.dependency_overrides[get_user_service] = lambda: user_service response = client.post( "/auth/login", data={"username": "testuser", "password": "wrong"}, ) assert response.status_code == status.HTTP_401_UNAUTHORIZED # ---------------------- TESTS FOR /auth/me ---------------------- class TesteMe: def test_i_can_get_current_user_profile(self, client, fake_user): client.app.dependency_overrides[get_current_user] = override_get_current_user(fake_user) response = client.get("/auth/me") assert response.status_code == status.HTTP_200_OK data = response.json() assert data["username"] == fake_user.username assert data["email"] == fake_user.email def test_i_cannot_get_profile_without_authentication(self, client, monkeypatch): def raise_http_exception(): raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED) client.app.dependency_overrides[get_current_user] = raise_http_exception response = client.get("/auth/me") assert response.status_code == status.HTTP_401_UNAUTHORIZED