Compare commits

...

2 Commits

Author SHA1 Message Date
CI Bot 44648320df style: auto-format with black + isort + prettier [skip ci-format-check]
PR Automation / Auto Merge on CI Green + Approved (pull_request) Failing after 1s
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 44s
CI/CD Pipeline / PR Build Worker Image (pull_request) Failing after 0s
AI Code Review / AI Code Review (pull_request) Failing after 2m4s
CI/CD Pipeline / Validate - Migration (alembic) (pull_request) Successful in 2m12s
CI/CD Pipeline / Validate - Type Check (mypy) (pull_request) Successful in 2m23s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 2m24s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m30s
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 3m41s
CI/CD Pipeline / Unit Tests (pull_request) Successful in 4m1s
CI/CD Pipeline / Validate - Code Quality (pull_request) Successful in 6m59s
CI/CD Pipeline / Integration Tests (pull_request) Successful in 2m32s
CI/CD Pipeline / CI Gate (pull_request) Failing after 5s
ACR Cleanup / ACR Image Cleanup (pull_request_target) Successful in 29s
Preview Cleanup / Cleanup Preview Environment (pull_request) Successful in 1m2s
CI/CD Pipeline / Production Browser E2E (pull_request) Failing after 714h21m43s
CI/CD Pipeline / Deploy Production (pull_request) Failing after 714h21m44s
CI/CD Pipeline / Build Production Worker Image (pull_request) Failing after 714h21m45s
CI/CD Pipeline / Build Production Web Image (pull_request) Failing after 714h21m45s
CI/CD Pipeline / Build Production API Image (pull_request) Failing after 714h21m45s
CI/CD Pipeline / PR Build Web Image (pull_request) Failing after 714h27m58s
CI/CD Pipeline / Frontend Unit Tests (pull_request) Failing after 714h28m0s
CI/CD Pipeline / Frontend Lint (pull_request) Failing after 714h28m0s
CI/CD Pipeline / Staging API Integration Tests (pull_request) Failing after 714h28m38s
CI/CD Pipeline / Staging E2E Tests (pull_request) Failing after 714h28m38s
CI/CD Pipeline / Build Staging Worker Image (pull_request) Failing after 714h28m44s
CI/CD Pipeline / Build Staging API Image (pull_request) Failing after 714h28m45s
CI/CD Pipeline / Build Staging Web Image (pull_request) Failing after 714h28m45s
CI/CD Pipeline / Canary Release to Production (pull_request) Failing after 714h55m22s
CI/CD Pipeline / ACR Image Cleanup (pull_request) Failing after 715h2m16s
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Failing after 715h2m18s
2026-08-17 12:57:44 +00:00
CI Bot a6baaf9829 fix(test): harden batch_download session tests with multi-path patching + diagnostic
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 21s
CI/CD Pipeline / Validate - Migration (alembic) (pull_request) Successful in 1m49s
AI Code Review / AI Code Review (pull_request) Failing after 1m53s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 1m53s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 2m6s
CI/CD Pipeline / Validate - Type Check (mypy) (pull_request) Successful in 3m11s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m59s
CI/CD Pipeline / Validate - Code Quality (pull_request) Has been cancelled
CI/CD Pipeline / Unit Tests (pull_request) Has been cancelled
CI/CD Pipeline / Integration Tests (pull_request) Has been cancelled
CI/CD Pipeline / PR Build API Image (pull_request) Has been cancelled
CI/CD Pipeline / PR Build Worker Image (pull_request) Has been cancelled
CI/CD Pipeline / Build Production API Image (pull_request) Has been cancelled
CI/CD Pipeline / Build Production Web Image (pull_request) Has been cancelled
CI/CD Pipeline / Build Production Worker Image (pull_request) Has been cancelled
CI/CD Pipeline / Deploy Production (pull_request) Has been cancelled
CI/CD Pipeline / Production Browser E2E (pull_request) Has been cancelled
CI/CD Pipeline / Canary Release to Production (pull_request) Has been cancelled
CI/CD Pipeline / CI Gate (pull_request) Has been cancelled
CI/CD Pipeline / PR Build Web Image (pull_request) Failing after 714h32m37s
CI/CD Pipeline / Frontend Unit Tests (pull_request) Failing after 714h32m39s
CI/CD Pipeline / ACR Image Cleanup (pull_request) Failing after 714h32m55s
CI/CD Pipeline / Staging API Integration Tests (pull_request) Failing after 714h32m57s
CI/CD Pipeline / Build Staging Worker Image (pull_request) Failing after 714h33m1s
CI/CD Pipeline / Staging E2E Tests (pull_request) Failing after 714h32m57s
CI/CD Pipeline / Build Staging Web Image (pull_request) Failing after 714h33m2s
CI/CD Pipeline / Build Staging API Image (pull_request) Failing after 714h33m2s
CI/CD Pipeline / Frontend Lint (pull_request) Failing after 715h6m17s
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Failing after 715h6m37s
Full-suite runs showed test_batch_download_session_closed and
test_batch_download_closes_session_on_error failing with
"Expected close to have been called once. Called 0 times."

Changes:
- Patch SessionLocal in all possible locations: _db_mod, sys.modules,
  and function globals (if present)
- Call raw_fn directly instead of going through _call_task
- Add diagnostic assertion to verify mock_session_factory was called
- Remove try/finally restore (not needed for isolated tests)

Also includes fix from PR #1407: add missing str fields to mock clip.
2026-08-17 20:53:16 +08:00
+41 -11
View File
@@ -256,9 +256,11 @@ def test_batch_download_single_video():
def test_batch_download_session_closed():
"""DB session is always closed (via finally block).
Self-contained: uses patch.object on the actual worker_app.db module
to avoid stale PromiseProxy cache from prior tests in the suite.
Patches the function's own globals to inject mock SessionLocal,
bypassing any import caching issues in the full suite.
"""
import sys
import worker_app.db as _db_mod
from apps.worker.worker_app.tasks.batch_download import batch_download_videos
@@ -267,6 +269,7 @@ def test_batch_download_session_closed():
repo = _FakeGeneratedVideoRepository(videos)
session = MagicMock()
mock_session_factory = MagicMock(return_value=session)
def _noop_download(url, dest):
Path(dest).parent.mkdir(parents=True, exist_ok=True)
@@ -274,7 +277,19 @@ def test_batch_download_session_closed():
bound_task = _make_bound_task()
with patch.object(_db_mod, "SessionLocal", MagicMock(return_value=session)):
# Get the raw function to patch its globals
raw_fn = _get_raw_task_fn(batch_download_videos)
# Patch SessionLocal in ALL possible module locations
_db_mod.SessionLocal = mock_session_factory
if "worker_app.db" in sys.modules:
sys.modules["worker_app.db"].SessionLocal = mock_session_factory
# Also patch in the function's own globals if it has a reference there
if "SessionLocal" in raw_fn.__globals__:
raw_fn.__globals__["SessionLocal"] = mock_session_factory
try:
with patch(
"packages.adapters.sqlalchemy_impl.generated_video_repository.SQLAlchemyGeneratedVideoRepository",
return_value=repo,
@@ -284,13 +299,19 @@ def test_batch_download_session_closed():
"apps.worker.worker_app.tasks.batch_download._download_video_to_file",
_noop_download,
):
_call_task(batch_download_videos, bound_task, ["v1"], "user_1")
raw_fn(bound_task, ["v1"], "user_1")
finally:
pass # Don't restore - other tests handle their own patches
# Diagnostic: check if our mock factory was actually called
assert mock_session_factory.called, "SessionLocal mock was never called! " f"raw_fn={raw_fn}, type={type(raw_fn)}"
session.close.assert_called_once()
def test_batch_download_closes_session_on_error():
"""Session is closed even when get_by_ids raises."""
import sys
import worker_app.db as _db_mod
from apps.worker.worker_app.tasks.batch_download import batch_download_videos
@@ -300,16 +321,25 @@ def test_batch_download_closes_session_on_error():
raise RuntimeError("db down")
session = MagicMock()
mock_session_factory = MagicMock(return_value=session)
bound_task = _make_bound_task()
with patch.object(_db_mod, "SessionLocal", MagicMock(return_value=session)):
with patch(
"packages.adapters.sqlalchemy_impl.generated_video_repository.SQLAlchemyGeneratedVideoRepository",
return_value=_ExplodingRepo(),
):
with pytest.raises(RuntimeError, match="db down"):
_call_task(batch_download_videos, bound_task, ["v1"], "u")
raw_fn = _get_raw_task_fn(batch_download_videos)
_db_mod.SessionLocal = mock_session_factory
if "worker_app.db" in sys.modules:
sys.modules["worker_app.db"].SessionLocal = mock_session_factory
if "SessionLocal" in raw_fn.__globals__:
raw_fn.__globals__["SessionLocal"] = mock_session_factory
with patch(
"packages.adapters.sqlalchemy_impl.generated_video_repository.SQLAlchemyGeneratedVideoRepository",
return_value=_ExplodingRepo(),
):
with pytest.raises(RuntimeError, match="db down"):
raw_fn(bound_task, ["v1"], "u")
assert mock_session_factory.called, "SessionLocal mock was never called!"
session.close.assert_called_once()