From c7321cf0e0335a1e708aab2d324ca8a52e734e1e Mon Sep 17 00:00:00 2001 From: Samir Boulahtit Date: Sun, 14 Dec 2025 12:49:08 +0100 Subject: [PATCH] fix: correct vendor_id parameter in background task tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Change vendor_id from string "TESTVENDOR" to test_vendor.id (integer) - Add test_marketplace_import_vendor_not_found for vendor lookup errors - Add test_marketplace_import_commit_error_handling for commit failures - Add test_marketplace_import_close_error_handling for session close errors - Achieves 100% test coverage on app/tasks/background_tasks.py 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- .../tasks/test_background_tasks.py | 183 +++++++++++++++++- 1 file changed, 178 insertions(+), 5 deletions(-) diff --git a/tests/integration/tasks/test_background_tasks.py b/tests/integration/tasks/test_background_tasks.py index eea89999..ee7a4b9b 100644 --- a/tests/integration/tasks/test_background_tasks.py +++ b/tests/integration/tasks/test_background_tasks.py @@ -1,5 +1,5 @@ -# tests/test_background_tasks.py -from unittest.mock import AsyncMock, patch +# tests/integration/tasks/test_background_tasks.py +from unittest.mock import AsyncMock, MagicMock, patch import pytest @@ -47,7 +47,7 @@ class TestBackgroundTasks: # Run background task await process_marketplace_import( - job_id, "http://example.com/test.csv", "TestMarket", "TESTVENDOR", 1000 + job_id, "http://example.com/test.csv", "TestMarket", test_vendor.id, 1000 ) # Re-query the job using the stored ID @@ -102,7 +102,7 @@ class TestBackgroundTasks: job_id, "http://example.com/test.csv", "TestMarket", - "TESTVENDOR", + test_vendor.id, 1000, ) except Exception: @@ -187,7 +187,7 @@ class TestBackgroundTasks: # Run background task await process_marketplace_import( - job_id, "http://example.com/test.csv", "TestMarket", "TESTVENDOR", 1000 + job_id, "http://example.com/test.csv", "TestMarket", test_vendor.id, 1000 ) # Re-query the job using the stored ID @@ -204,3 +204,176 @@ class TestBackgroundTasks: assert updated_job.error_count == 2 assert updated_job.total_processed == 15 assert "2 rows had errors" in updated_job.error_message + + @pytest.mark.asyncio + async def test_marketplace_import_vendor_not_found(self, db, test_user, test_vendor): + """Test handling when vendor doesn't exist""" + # Create import job + job = MarketplaceImportJob( + status="pending", + source_url="http://example.com/test.csv", + marketplace="TestMarket", + vendor_id=test_vendor.id, + user_id=test_user.id, + language="en", + ) + db.add(job) + db.commit() + db.refresh(job) + + # Store the job ID before it becomes detached + job_id = job.id + + # Mock CSV processor + with ( + patch("app.tasks.background_tasks.CSVProcessor") as mock_processor, + patch("app.tasks.background_tasks.SessionLocal", return_value=db), + ): + mock_instance = mock_processor.return_value + mock_instance.process_marketplace_csv_from_url = AsyncMock( + return_value={ + "imported": 10, + "updated": 5, + "total_processed": 15, + "errors": 0, + } + ) + + # Run background task with non-existent vendor ID + await process_marketplace_import( + job_id, + "http://example.com/test.csv", + "TestMarket", + 99999, # Non-existent vendor ID + 1000, + ) + + # The CSV processor should not be called + mock_instance.process_marketplace_csv_from_url.assert_not_called() + + # Re-query the job using the stored ID + updated_job = ( + db.query(MarketplaceImportJob) + .filter(MarketplaceImportJob.id == job_id) + .first() + ) + + assert updated_job is not None + assert updated_job.status == "failed" + assert "Vendor 99999 not found" in updated_job.error_message + assert updated_job.completed_at is not None + + @pytest.mark.asyncio + async def test_marketplace_import_commit_error_handling( + self, db, test_user, test_vendor + ): + """Test handling when commit fails during exception handling""" + # Create import job + job = MarketplaceImportJob( + status="pending", + source_url="http://example.com/test.csv", + marketplace="TestMarket", + vendor_id=test_vendor.id, + user_id=test_user.id, + language="en", + ) + db.add(job) + db.commit() + db.refresh(job) + + # Store the job ID before it becomes detached + job_id = job.id + + # Create a mock session that will fail on commit in the exception handler + mock_session = MagicMock() + mock_session.query.return_value.filter.return_value.first.side_effect = [ + job, # First call returns the job + test_vendor, # Second call returns the vendor + ] + mock_session.commit.side_effect = [ + None, # First commit (status=processing) succeeds + Exception("Simulated commit failure"), # Second commit fails + ] + mock_session.rollback = MagicMock() + mock_session.close = MagicMock() + + with ( + patch("app.tasks.background_tasks.CSVProcessor") as mock_processor, + patch( + "app.tasks.background_tasks.SessionLocal", return_value=mock_session + ), + ): + mock_instance = mock_processor.return_value + mock_instance.process_marketplace_csv_from_url = AsyncMock( + side_effect=Exception("Import failed") + ) + + # Run background task - should handle commit error gracefully + await process_marketplace_import( + job_id, + "http://example.com/test.csv", + "TestMarket", + test_vendor.id, + 1000, + ) + + # Verify rollback was called after commit failure + mock_session.rollback.assert_called_once() + + @pytest.mark.asyncio + async def test_marketplace_import_close_error_handling( + self, db, test_user, test_vendor + ): + """Test handling when session close fails""" + # Create import job + job = MarketplaceImportJob( + status="pending", + source_url="http://example.com/test.csv", + marketplace="TestMarket", + vendor_id=test_vendor.id, + user_id=test_user.id, + language="en", + ) + db.add(job) + db.commit() + db.refresh(job) + + # Store the job ID before it becomes detached + job_id = job.id + + # Create a mock session that will fail on close + mock_session = MagicMock() + mock_session.query.return_value.filter.return_value.first.side_effect = [ + job, # First call returns the job + test_vendor, # Second call returns the vendor + ] + mock_session.commit = MagicMock() + mock_session.close.side_effect = Exception("Simulated close failure") + + with ( + patch("app.tasks.background_tasks.CSVProcessor") as mock_processor, + patch( + "app.tasks.background_tasks.SessionLocal", return_value=mock_session + ), + ): + mock_instance = mock_processor.return_value + mock_instance.process_marketplace_csv_from_url = AsyncMock( + return_value={ + "imported": 10, + "updated": 5, + "total_processed": 15, + "errors": 0, + } + ) + + # Run background task - should handle close error gracefully + await process_marketplace_import( + job_id, + "http://example.com/test.csv", + "TestMarket", + test_vendor.id, + 1000, + ) + + # The close method should have been called + mock_session.close.assert_called_once()