Files
mostovik-backend/tests/apps/exchange/test_tasks.py
Aleksandr Meshchriakov 3de66cc25c
Some checks failed
CI/CD Pipeline / Code Quality Checks (push) Successful in 3m16s
CI/CD Pipeline / Run Tests (push) Successful in 3m26s
CI/CD Pipeline / Telegram Notify Success (push) Failing after 1m29s
CI/CD Pipeline / Run Tests (pull_request) Successful in 1m44s
CI/CD Pipeline / Code Quality Checks (pull_request) Successful in 20m19s
CI/CD Pipeline / Telegram Notify Success (pull_request) Failing after 1m34s
Add periodic exchange task management API
2026-03-19 17:03:47 +01:00

167 lines
6.6 KiB
Python

from __future__ import annotations
from unittest.mock import MagicMock, patch
from apps.exchange.services import ExchangeServiceError
from apps.exchange.tasks import copy_parsers_data_async, dispatch_periodic_exchange_copy
from django.test import SimpleTestCase
class ExchangeTasksTest(SimpleTestCase):
def test_dispatch_periodic_exchange_copy_enqueues_copy_with_active_connection(self):
active_connection = MagicMock(id=15)
with patch(
"apps.exchange.tasks.ExchangeConnectionService.get_active_connection",
return_value=active_connection,
) as get_connection_mock, patch(
"apps.exchange.tasks.copy_parsers_data_async.delay",
return_value=MagicMock(id="task-15"),
) as delay_mock:
result = dispatch_periodic_exchange_copy.run(
payload={"mode": "all", "truncate_before_copy": True}
)
self.assertEqual(
result,
{
"status": "queued",
"task_id": "task-15",
"connection_id": 15,
},
)
get_connection_mock.assert_called_once_with()
delay_mock.assert_called_once_with(
connection_id=15,
payload={"mode": "all", "truncate_before_copy": True},
requested_by_id=None,
)
def test_dispatch_periodic_exchange_copy_fails_without_active_connection(self):
with patch(
"apps.exchange.tasks.ExchangeConnectionService.get_active_connection",
side_effect=ExchangeServiceError("Активное подключение не найдено"),
), self.assertRaisesMessage(
ExchangeServiceError,
"Активное подключение не найдено",
):
dispatch_periodic_exchange_copy.run(payload={"mode": "all"})
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, patch(
"apps.exchange.tasks.ExchangeConnection.objects.filter",
) as filter_mock, 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"
), patch(
"apps.exchange.tasks.BackgroundJobService.get_by_task_id_or_none",
return_value=None,
), patch(
"apps.exchange.tasks.BackgroundJobService.create_job",
return_value=background_job,
) as create_job_mock, patch(
"apps.exchange.tasks.ExchangeConnection.objects.filter",
) as filter_mock, self.assertRaisesMessage(
ValueError,
"Active exchange connection not found: 42",
):
filter_mock.return_value.first.return_value = None
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,
), patch(
"apps.exchange.tasks.ExchangeConnection.objects.filter",
) as filter_mock, patch(
"apps.exchange.tasks.ExchangeConnectionService.copy_parsers_data",
side_effect=RuntimeError("copy failed"),
), patch(
"apps.exchange.tasks.logger.exception"
) as logger_mock, self.assertRaisesMessage(RuntimeError, "copy failed"):
filter_mock.return_value.first.return_value = connection
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()