"""真实分页进度在每页提交后可读;总量未知或失败时不伪造成功。""" from datetime import datetime from unittest.mock import Mock from sqlalchemy import select from app.models import TPlusSyncBatch from app.services.tplus import progress from app.services.tplus.sync_service import TPlusSyncService from tests.unit.test_tplus_sync import target as target def test_每页提交真实已读数及类别(target): service = TPlusSyncService(Mock(), target) service.reader = Mock() service.reader.count_entities.return_value = {"products": 2} def rows(*args, **kwargs): yield {"id": 1} batch = target.scalar(select(TPlusSyncBatch)) item = progress.public(batch) assert item["processed_records"] == 1 and item["total_records"] == 2 assert item["percentage"] == 50.0 and item["active_entity"] == "products" yield {"id": 2} service.reader.iter_entity.side_effect = rows batch = service.run(entity_types=["products"], batch_size=1) item = progress.public(batch) assert batch.status == "SUCCEEDED" and item["percentage"] == 100.0 assert item["entities"][0]["status"] == "COMPLETED" def test_总量统计失败仍可读且执行中总量未知(target): source = Mock() service = TPlusSyncService(source, target) service.reader = Mock() service.reader.count_entities.side_effect = RuntimeError("不得公开的数据库详情") def rows(*args, **kwargs): batch = target.scalar(select(TPlusSyncBatch)) assert progress.public(batch)["percentage"] is None yield {"id": 1} service.reader.iter_entity.side_effect = rows batch = service.run(entity_types=["products"]) assert batch.status == "SUCCEEDED" source.rollback.assert_called_once() def test_读取中断保留进度及错误终态(target): service = TPlusSyncService(Mock(), target) service.reader = Mock() service.reader.count_entities.return_value = {"products": 4} def rows(*args, **kwargs): yield {"id": 1} raise TimeoutError("敏感详情") service.reader.iter_entity.side_effect = rows batch = service.run(entity_types=["products"], batch_size=1) item = progress.public(batch) assert batch.status == "FAILED" and item["percentage"] == 25.0 assert item["phase"] == "FAILED" and item["entities"][0]["status"] == "FAILED" def test_旧批次未知总量不显示编造百分比(): batch = TPlusSyncBatch(batch_no="old", sync_mode="FULL", status="RUNNING", source_record_count=1000, entity_types_json=["personnel"], started_at=datetime.now()) item = progress.public(batch) assert item["percentage"] is None and item["total_records"] is None assert item["processed_records"] == 1000 def test_读到预统计总量仍等终态才显示百分之百(): batch = TPlusSyncBatch(batch_no="b", sync_mode="FULL", status="RUNNING", source_record_count=10, entity_types_json=["products"], started_at=datetime.now(), audit_result_json={"progress": {"total_records": 10}}) assert progress.public(batch)["percentage"] == 99.9 batch.status = "SUCCEEDED" assert progress.public(batch)["percentage"] == 100.0