Application fully migrated to modular approach
This commit is contained in:
@@ -3,26 +3,32 @@ import pytest
|
||||
from unittest.mock import patch, AsyncMock
|
||||
from app.tasks.background_tasks import process_marketplace_import
|
||||
from models.database_models import MarketplaceImportJob
|
||||
from datetime import datetime
|
||||
|
||||
|
||||
class TestBackgroundTasks:
|
||||
@pytest.mark.asyncio
|
||||
async def test_marketplace_import_success(self, db):
|
||||
async def test_marketplace_import_success(self, db, test_user, test_shop):
|
||||
"""Test successful marketplace import background task"""
|
||||
# Create import job
|
||||
job = MarketplaceImportJob(
|
||||
status="pending",
|
||||
source_url="http://example.com/test.csv",
|
||||
shop_name="TESTSHOP",
|
||||
marketplace="TestMarket",
|
||||
shop_code="TESTSHOP",
|
||||
user_id=1
|
||||
shop_id=test_shop.id,
|
||||
user_id=test_user.id
|
||||
)
|
||||
db.add(job)
|
||||
db.commit()
|
||||
db.refresh(job)
|
||||
|
||||
# Mock CSV processor
|
||||
with patch('app.tasks.background_tasks.CSVProcessor') as mock_processor:
|
||||
# Store the job ID before it becomes detached
|
||||
job_id = job.id
|
||||
|
||||
# Mock CSV processor and prevent session from closing
|
||||
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,
|
||||
@@ -33,51 +39,153 @@ class TestBackgroundTasks:
|
||||
|
||||
# Run background task
|
||||
await process_marketplace_import(
|
||||
job.id,
|
||||
job_id,
|
||||
"http://example.com/test.csv",
|
||||
"TestMarket",
|
||||
"TESTSHOP",
|
||||
1000
|
||||
)
|
||||
|
||||
# Verify job was updated
|
||||
db.refresh(job)
|
||||
assert job.status == "completed"
|
||||
assert job.imported_count == 10
|
||||
assert job.updated_count == 5
|
||||
# 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 == "completed"
|
||||
assert updated_job.imported_count == 10
|
||||
assert updated_job.updated_count == 5
|
||||
assert updated_job.total_processed == 15
|
||||
assert updated_job.error_count == 0
|
||||
assert updated_job.started_at is not None
|
||||
assert updated_job.completed_at is not None
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_marketplace_import_failure(self, db):
|
||||
async def test_marketplace_import_failure(self, db, test_user, test_shop):
|
||||
"""Test marketplace import failure handling"""
|
||||
# Create import job
|
||||
job = MarketplaceImportJob(
|
||||
status="pending",
|
||||
source_url="http://example.com/test.csv",
|
||||
shop_name="TESTSHOP",
|
||||
marketplace="TestMarket",
|
||||
shop_code="TESTSHOP",
|
||||
user_id=1
|
||||
shop_id=test_shop.id,
|
||||
user_id=test_user.id
|
||||
)
|
||||
db.add(job)
|
||||
db.commit()
|
||||
db.refresh(job)
|
||||
|
||||
# Store the job ID before it becomes detached
|
||||
job_id = job.id
|
||||
|
||||
# Mock CSV processor to raise exception
|
||||
with patch('app.tasks.background_tasks.CSVProcessor') as mock_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(
|
||||
side_effect=Exception("Import failed")
|
||||
)
|
||||
|
||||
# Run background task
|
||||
# Run background task - this should not raise the exception
|
||||
# because it's handled in the background task
|
||||
try:
|
||||
await process_marketplace_import(
|
||||
job_id,
|
||||
"http://example.com/test.csv",
|
||||
"TestMarket",
|
||||
"TESTSHOP",
|
||||
1000
|
||||
)
|
||||
except Exception:
|
||||
# The background task should handle exceptions internally
|
||||
# If an exception propagates here, that's a bug in the background task
|
||||
pass
|
||||
|
||||
# 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 "Import failed" in updated_job.error_message
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_marketplace_import_job_not_found(self, db):
|
||||
"""Test handling when import job doesn't exist"""
|
||||
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 job ID
|
||||
await process_marketplace_import(
|
||||
job.id,
|
||||
999, # Non-existent job ID
|
||||
"http://example.com/test.csv",
|
||||
"TestMarket",
|
||||
"TESTSHOP",
|
||||
1000
|
||||
)
|
||||
|
||||
# Verify job failure was recorded
|
||||
db.refresh(job)
|
||||
assert job.status == "failed"
|
||||
assert "Import failed" in job.error_message
|
||||
# Should not raise an exception, just log and return
|
||||
# The CSV processor should not be called
|
||||
mock_instance.process_marketplace_csv_from_url.assert_not_called()
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_marketplace_import_with_errors(self, db, test_user, test_shop):
|
||||
"""Test marketplace import with some errors"""
|
||||
# Create import job
|
||||
job = MarketplaceImportJob(
|
||||
status="pending",
|
||||
source_url="http://example.com/test.csv",
|
||||
shop_name="TESTSHOP",
|
||||
marketplace="TestMarket",
|
||||
shop_id=test_shop.id,
|
||||
user_id=test_user.id
|
||||
)
|
||||
db.add(job)
|
||||
db.commit()
|
||||
db.refresh(job)
|
||||
|
||||
# Store the job ID before it becomes detached
|
||||
job_id = job.id
|
||||
|
||||
# Mock CSV processor with some errors
|
||||
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": 8,
|
||||
"updated": 5,
|
||||
"total_processed": 15,
|
||||
"errors": 2
|
||||
})
|
||||
|
||||
# Run background task
|
||||
await process_marketplace_import(
|
||||
job_id,
|
||||
"http://example.com/test.csv",
|
||||
"TestMarket",
|
||||
"TESTSHOP",
|
||||
1000
|
||||
)
|
||||
|
||||
# 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 == "completed_with_errors"
|
||||
assert updated_job.imported_count == 8
|
||||
assert updated_job.updated_count == 5
|
||||
assert updated_job.error_count == 2
|
||||
assert updated_job.total_processed == 15
|
||||
assert "2 rows had errors" in updated_job.error_message
|
||||
|
||||
Reference in New Issue
Block a user