# 통합 테스트 시나리오 import pytest from fastapi.testclient import TestClient from unittest.mock import MagicMock, AsyncMock, patch from tests.utils import TestUtils from app.dependencies import get_auth_service, get_user_service, get_video_service class TestIntegrationScenarios: """엔드투엔드 통합 테스트 시나리오""" def test_complete_user_journey(self, client, mock_auth_service, mock_user_service, mock_video_service): """사용자의 전체 여정 테스트: 회원가입 → 로그인 → 프로필 → 아이템 → 비디오""" utils = TestUtils() # 1. 회원가입 client.app.dependency_overrides[get_auth_service] = lambda: mock_auth_service mock_auth_service.join.return_value = utils.create_test_user() response = client.post("/api/v1/auth/join", json={ "email": "newuser@example.com", "password": "NewUser1234!", "password_confirm": "NewUser1234!", "name": "New User" }) user_data = utils.assert_response_success(response) user_id = user_data["id"] # 2. 로그인 mock_auth_service.login.return_value = { "access_token": utils.create_test_token(user_id), "token_type": "bearer", "user_id": user_id } response = client.post("/api/v1/auth/login", json={ "email": "newuser@example.com", "password": "NewUser1234!" }) login_data = utils.assert_response_success(response) token = login_data["access_token"] # 3. 인증 헤더 설정 client.headers = {"Authorization": f"Bearer {token}"} # 4. 프로필 조회 client.app.dependency_overrides[get_user_service] = lambda: mock_user_service mock_user_service.get_user_profile.return_value = { "user_id": user_id, "email": "newuser@example.com", "name": "New User", "bio": None } response = client.post("/api/v1/user/profile", json={"user_id": user_id}) profile_data = utils.assert_response_success(response) # 5. 프로필 업데이트 mock_user_service.update_user_profile.return_value = { "user_id": user_id, "name": "Updated User", "bio": "I love making videos!", "updated": True } response = client.put("/api/v1/user/profile/update", json={ "user_id": user_id, "name": "Updated User", "bio": "I love making videos!" }) utils.assert_response_success(response) # 6. 아이템 생성 시뮬레이션 (서비스에서 처리) mock_user_service.get_items.return_value = { "items": [utils.create_test_item(1, user_id)], "total": 1 } response = client.post("/api/v1/user/items", json={ "user_id": user_id, "page": 1, "limit": 10 }) items_data = utils.assert_response_success(response) assert items_data["total"] == 1 # 7. 비디오 생성 시뮬레이션 client.app.dependency_overrides[get_video_service] = lambda: mock_video_service mock_video_service.get_all_by_user_id.return_value = { "videos": [utils.create_test_video(1, user_id)], "total": 1 } response = client.post("/api/v1/user/videos", json={ "user_id": user_id, "page": 1, "limit": 10 }) videos_data = utils.assert_response_success(response) assert videos_data["total"] == 1 def test_moviemaker_workflow_complete(self, client, mock_redis_manager): """MovieMaker 워크플로우 전체 과정 테스트""" utils = TestUtils() # 1. 워크플로우 시작 with patch('app.presentation.api.v1.moviemakers.RedisManager', return_value=mock_redis_manager): with patch('app.presentation.api.v1.moviemakers.Process') as mock_process_class: mock_process = MagicMock() mock_process.init_task_status = AsyncMock(return_value=None) mock_process_class.return_value = mock_process # Celery tasks mock with patch('app.workers.tasks.task1_crawl.s'), \ patch('app.workers.tasks.task2_generate_lyrics.s'), \ patch('app.workers.tasks.task3_generate_music.s'), \ patch('app.workers.tasks.task1_crawl_images.s'), \ patch('app.workers.tasks.task4_generate_video.s'), \ patch('app.workers.tasks.task5_merge_results.s'): response = client.post("/api/v1/moviemaker/start-workflow", json={ "url": "https://example.com/video" }) workflow_data = utils.assert_response_success(response) task_id = workflow_data["task_id"] # 2. 진행상황 확인 - 초기 상태 mock_process.get_task_status = AsyncMock(return_value={ "metadata": True, "lyrics": False, "songs": False, "images": False, "movies": False, "combined": False }) response = client.post("/api/v1/moviemaker/progress", json={ "task_id": task_id }) progress_data = response.json() assert progress_data["progress"]["metadata"] == True assert progress_data["progress"]["lyrics"] == False # 3. 진행상황 확인 - 중간 상태 mock_process.get_task_status = AsyncMock(return_value={ "metadata": True, "lyrics": True, "songs": True, "images": True, "movies": False, "combined": False }) response = client.post("/api/v1/moviemaker/progress", json={ "task_id": task_id }) progress_data = response.json() assert progress_data["progress"]["songs"] == True assert progress_data["progress"]["movies"] == False # 4. 진행상황 확인 - 완료 상태 mock_process.get_task_status = AsyncMock(return_value={ "metadata": True, "lyrics": True, "songs": True, "images": True, "movies": True, "combined": True }) response = client.post("/api/v1/moviemaker/progress", json={ "task_id": task_id }) progress_data = response.json() assert all(progress_data["progress"].values()) == True def test_google_oauth_flow(self, client, mock_google_service): """Google OAuth 전체 플로우 테스트""" utils = TestUtils() # 1. Google 로그인 URL 요청 client.app.dependency_overrides[get_google_service] = lambda: mock_google_service mock_google_service.get_login_url.return_value = { "url": "https://accounts.google.com/oauth2/v2/auth?client_id=test" } response = client.get("/api/v1/social/google/login?return_url=/dashboard") assert response.status_code == 200 # 2. Google OAuth 콜백 처리 mock_result = MagicMock() mock_result.temp_token_id = "temp_google_token_123" mock_result.return_url = "/dashboard" mock_google_service.handle_callback.return_value = mock_result response = client.get("/api/v1/social/google/callback?code=google_auth_code&state=state_data") assert response.status_code == 307 # Redirect assert "temp_google_token_123" in response.headers["location"] # 3. 임시 토큰으로 정보 조회 google_data = utils.create_google_oauth_data() mock_google_service.get_token_by_temp_id.return_value = google_data response = client.get("/api/v1/social/google/token/temp_google_token_123") token_data = utils.assert_response_success(response) assert token_data["user_info"]["email"] == "test@gmail.com"