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
167 lines
6.6 KiB
Python
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()
|