import unittest from unittest.mock import patch from app.services.sync_push_service import ( _extract_detect_result_projection_events, ingest_runtime_projection, ) class _FakeCursor: def __init__(self, rows): self._rows = list(rows) self.executed = [] def execute(self, sql, params=None): self.executed.append((sql, params)) def fetchone(self): if self._rows: return self._rows.pop(0) return None def __enter__(self): return self def __exit__(self, exc_type, exc, tb): return False class _FakeConnection: def __init__(self, rows): self.cursor_obj = _FakeCursor(rows) self.committed = False def cursor(self): return self.cursor_obj def commit(self): self.committed = True def __enter__(self): return self def __exit__(self, exc_type, exc, tb): return False class SyncPushServiceTests(unittest.TestCase): def test_extract_detect_result_projection_events_adds_import_metadata(self) -> None: projection = { "job": { "job_id": 12, "job_code": "detect-local-001", }, "recent_domain_events": [ { "node_code": "mainland-worker-01", "event_type": "domain_completed", "level": "info", "message": "完成 a.com", "created_at": "2026-04-19 01:05:00", "payload": {"domain": "a.com", "domain_id": 101, "cycle_token": "cycle-1"}, } ], } events = _extract_detect_result_projection_events( source_region="mainland", source_record_id=88, projection=projection, ) self.assertEqual(1, len(events)) event = events[0] self.assertEqual("domain_completed", event["event_type"]) self.assertEqual("mainland", event["payload"]["import_source_region"]) self.assertEqual(88, event["payload"]["import_source_record_id"]) self.assertEqual("detect-local-001", event["payload"]["import_source_job_code"]) self.assertTrue(event["payload"]["imported_from_projection"]) self.assertTrue(event["payload"]["import_fingerprint"]) @patch("app.services.sync_push_service._import_detect_result_projection_events") @patch("app.services.sync_push_service.get_db") def test_ingest_runtime_projection_imports_detect_result_events_on_new_record( self, mock_get_db, mock_import_events, ) -> None: fake_conn = _FakeConnection(rows=[None, (321,)]) mock_get_db.return_value = fake_conn mock_import_events.return_value = {"imported_count": 2, "deduplicated_count": 0, "target_job_id": 9} ok, message, data = ingest_runtime_projection( { "sync_type": "detect_result_projection", "source_region": "mainland", "source_record_id": 66, "projection_hash": "hash-001", "projection": {"recent_domain_events": []}, } ) self.assertTrue(ok) self.assertEqual("同步投影接收成功", message) self.assertEqual(321, data["record_id"]) self.assertEqual(2, data["event_import"]["imported_count"]) mock_import_events.assert_called_once_with( source_region="mainland", source_record_id=66, projection={"recent_domain_events": []}, ) self.assertTrue(fake_conn.committed) @patch("app.services.sync_push_service._import_detect_result_projection_events") @patch("app.services.sync_push_service.get_db") def test_ingest_runtime_projection_imports_detect_result_events_on_deduplicated_record( self, mock_get_db, mock_import_events, ) -> None: fake_conn = _FakeConnection(rows=[(777,)]) mock_get_db.return_value = fake_conn mock_import_events.return_value = {"imported_count": 0, "deduplicated_count": 3, "target_job_id": 9} ok, message, data = ingest_runtime_projection( { "sync_type": "detect_result_projection", "source_region": "mainland", "source_record_id": 66, "projection_hash": "hash-001", "projection": {"recent_domain_events": []}, } ) self.assertTrue(ok) self.assertEqual("同步投影已存在,已按幂等处理", message) self.assertTrue(data["deduplicated"]) self.assertEqual(3, data["event_import"]["deduplicated_count"]) mock_import_events.assert_called_once_with( source_region="mainland", source_record_id=66, projection={"recent_domain_events": []}, ) if __name__ == "__main__": unittest.main()