from __future__ import annotations from unittest.mock import MagicMock, patch from apps.exchange.tasks import copy_parsers_data_async from django.test import SimpleTestCase class ExchangeTasksTest(SimpleTestCase): def test_copy_parsers_data_async_completes_with_existing_job(self): background_job = MagicMock() connection = MagicMock() copy_parsers_data_async.push_request(id="task-1") try: with patch( "apps.exchange.tasks.BackgroundJobService.get_by_task_id_or_none", return_value=background_job, ) as get_job_mock: with patch( "apps.exchange.tasks.ExchangeConnection.objects.filter", ) as filter_mock: with patch( "apps.exchange.tasks.ExchangeConnectionService.copy_parsers_data", return_value={ "mode": "all", "tables": ["fake_table"], "rows_by_table": {"fake_table": 3}, "total_rows": 3, "truncate_before_copy": True, }, ) as copy_mock: filter_mock.return_value.first.return_value = connection result = copy_parsers_data_async.run( connection_id=11, payload={"mode": "all", "truncate_before_copy": True}, requested_by_id=7, ) finally: copy_parsers_data_async.pop_request() self.assertEqual(result["status"], "success") self.assertEqual(result["connection_id"], 11) get_job_mock.assert_called_once_with("task-1") background_job.mark_started.assert_called_once_with() background_job.update_progress.assert_any_call( 10, "Проверка структуры целевой БД", ) background_job.update_progress.assert_any_call(90, "Фиксация результата") background_job.complete.assert_called_once_with(result=result) copy_mock.assert_called_once_with( connection=connection, mode="all", truncate_before_copy=True, ) def test_copy_parsers_data_async_creates_job_and_fails_when_connection_missing(self): background_job = MagicMock() copy_parsers_data_async.push_request(id=None) try: with patch("apps.exchange.tasks.uuid.uuid4", return_value="generated-task-id"): with patch( "apps.exchange.tasks.BackgroundJobService.get_by_task_id_or_none", return_value=None, ): with patch( "apps.exchange.tasks.BackgroundJobService.create_job", return_value=background_job, ) as create_job_mock: with patch( "apps.exchange.tasks.ExchangeConnection.objects.filter", ) as filter_mock: filter_mock.return_value.first.return_value = None with self.assertRaisesMessage( ValueError, "Active exchange connection not found: 42", ): copy_parsers_data_async.run( connection_id=42, payload={"mode": "all"}, requested_by_id=3, ) finally: copy_parsers_data_async.pop_request() create_job_mock.assert_called_once_with( task_id="generated-task-id", task_name="apps.exchange.tasks.copy_parsers_data_async", user_id=3, meta={"connection_id": 42, "mode": "all"}, ) background_job.fail.assert_called_once_with(error="Активное подключение не найдено") def test_copy_parsers_data_async_marks_failure_and_reraises(self): background_job = MagicMock() connection = MagicMock() copy_parsers_data_async.push_request(id="task-2") try: with patch( "apps.exchange.tasks.BackgroundJobService.get_by_task_id_or_none", return_value=background_job, ): with patch( "apps.exchange.tasks.ExchangeConnection.objects.filter", ) as filter_mock: with patch( "apps.exchange.tasks.ExchangeConnectionService.copy_parsers_data", side_effect=RuntimeError("copy failed"), ): with patch("apps.exchange.tasks.logger.exception") as logger_mock: filter_mock.return_value.first.return_value = connection with self.assertRaisesMessage(RuntimeError, "copy failed"): copy_parsers_data_async.run( connection_id=9, payload={"mode": "selected", "tables": ["fake_table"]}, ) finally: copy_parsers_data_async.pop_request() background_job.fail.assert_called_once_with(error="copy failed") logger_mock.assert_called_once()