fix pre-commit
Some checks failed
CI/CD Pipeline / Telegram Notify Success (push) Has been cancelled
CI/CD Pipeline / Run Tests (push) Has been cancelled
CI/CD Pipeline / Code Quality Checks (push) Has been cancelled
CI/CD Pipeline / Code Quality Checks (pull_request) Successful in 1m42s
CI/CD Pipeline / Run Tests (pull_request) Successful in 2m25s
CI/CD Pipeline / Telegram Notify Success (pull_request) Successful in 1m34s
Some checks failed
CI/CD Pipeline / Telegram Notify Success (push) Has been cancelled
CI/CD Pipeline / Run Tests (push) Has been cancelled
CI/CD Pipeline / Code Quality Checks (push) Has been cancelled
CI/CD Pipeline / Code Quality Checks (pull_request) Successful in 1m42s
CI/CD Pipeline / Run Tests (pull_request) Successful in 2m25s
CI/CD Pipeline / Telegram Notify Success (pull_request) Successful in 1m34s
This commit is contained in:
@@ -5,12 +5,19 @@ from types import SimpleNamespace
|
||||
from unittest.mock import MagicMock, patch
|
||||
|
||||
from apps.exchange.services import ExchangeConnectionService, ExchangeServiceError
|
||||
from apps.parsers.models import IndustrialCertificateRecord, ManufacturerRecord, ParserLoadLog
|
||||
from apps.parsers.models import (
|
||||
ManufacturerRecord,
|
||||
ParserLoadLog,
|
||||
)
|
||||
from django.test import TestCase
|
||||
|
||||
from tests.apps.exchange.factories import ExchangeConnectionFactory
|
||||
|
||||
|
||||
def _db_secret() -> str:
|
||||
return "secret"
|
||||
|
||||
|
||||
class _FakeModel:
|
||||
_meta = SimpleNamespace(
|
||||
app_label="tests",
|
||||
@@ -45,19 +52,18 @@ class ExchangeConnectionServiceUnitTest(TestCase):
|
||||
ExchangeConnectionService,
|
||||
"test_connection",
|
||||
return_value="target_alias",
|
||||
) as test_connection_mock:
|
||||
with patch.object(
|
||||
ExchangeConnectionService,
|
||||
"validate_target_structure",
|
||||
) as validate_mock:
|
||||
connection = ExchangeConnectionService.create_active_connection_and_prepare(
|
||||
server="127.0.0.1",
|
||||
port=5432,
|
||||
username="postgres",
|
||||
password="secret",
|
||||
database_name="target_db",
|
||||
schema_name="public",
|
||||
)
|
||||
) as test_connection_mock, patch.object(
|
||||
ExchangeConnectionService,
|
||||
"validate_target_structure",
|
||||
) as validate_mock:
|
||||
connection = ExchangeConnectionService.create_active_connection_and_prepare(
|
||||
server="127.0.0.1",
|
||||
port=5432,
|
||||
username="postgres",
|
||||
password=_db_secret(),
|
||||
database_name="target_db",
|
||||
schema_name="public",
|
||||
)
|
||||
|
||||
self.assertTrue(connection.is_active)
|
||||
self.assertIsNotNone(connection.last_checked_at)
|
||||
@@ -88,9 +94,8 @@ class ExchangeConnectionServiceUnitTest(TestCase):
|
||||
ExchangeConnectionService,
|
||||
"_configure_alias",
|
||||
return_value="exchange_target_1",
|
||||
):
|
||||
with patch("apps.exchange.services.connections", connections_mock):
|
||||
alias = ExchangeConnectionService.test_connection(connection)
|
||||
), patch("apps.exchange.services.connections", connections_mock):
|
||||
alias = ExchangeConnectionService.test_connection(connection)
|
||||
|
||||
self.assertEqual(alias, "exchange_target_1")
|
||||
db_connection.ensure_connection.assert_called_once_with()
|
||||
@@ -107,13 +112,13 @@ class ExchangeConnectionServiceUnitTest(TestCase):
|
||||
ExchangeConnectionService,
|
||||
"_configure_alias",
|
||||
return_value="exchange_target_1",
|
||||
), patch(
|
||||
"apps.exchange.services.connections", connections_mock
|
||||
), self.assertRaisesMessage(
|
||||
ExchangeServiceError,
|
||||
"Ошибка подключения к целевой БД: boom",
|
||||
):
|
||||
with patch("apps.exchange.services.connections", connections_mock):
|
||||
with self.assertRaisesMessage(
|
||||
ExchangeServiceError,
|
||||
"Ошибка подключения к целевой БД: boom",
|
||||
):
|
||||
ExchangeConnectionService.test_connection(connection)
|
||||
ExchangeConnectionService.test_connection(connection)
|
||||
|
||||
connection.refresh_from_db()
|
||||
self.assertEqual(connection.last_error, "boom")
|
||||
@@ -125,34 +130,31 @@ class ExchangeConnectionServiceUnitTest(TestCase):
|
||||
connections_mock = MagicMock()
|
||||
connections_mock.__getitem__.return_value = db_connection
|
||||
|
||||
with patch("apps.exchange.services.connections", connections_mock):
|
||||
with patch.object(
|
||||
ExchangeConnectionService,
|
||||
"_extend_models_with_dependencies",
|
||||
return_value=[_FakeModel],
|
||||
) as extend_mock:
|
||||
with patch.object(
|
||||
ExchangeConnectionService,
|
||||
"_get_parser_models",
|
||||
return_value=[_FakeModel],
|
||||
):
|
||||
with patch.object(
|
||||
ExchangeConnectionService,
|
||||
"_validate_schema_exists",
|
||||
) as schema_mock:
|
||||
with patch.object(
|
||||
ExchangeConnectionService,
|
||||
"_validate_tables_exist",
|
||||
) as tables_mock:
|
||||
with patch.object(
|
||||
ExchangeConnectionService,
|
||||
"_validate_columns_exist",
|
||||
) as columns_mock:
|
||||
ExchangeConnectionService.validate_target_structure(
|
||||
connection=connection,
|
||||
alias="target_alias",
|
||||
schema_name="public",
|
||||
)
|
||||
with patch(
|
||||
"apps.exchange.services.connections", connections_mock
|
||||
), patch.object(
|
||||
ExchangeConnectionService,
|
||||
"_extend_models_with_dependencies",
|
||||
return_value=[_FakeModel],
|
||||
) as extend_mock, patch.object(
|
||||
ExchangeConnectionService,
|
||||
"_get_parser_models",
|
||||
return_value=[_FakeModel],
|
||||
), patch.object(
|
||||
ExchangeConnectionService,
|
||||
"_validate_schema_exists",
|
||||
) as schema_mock, patch.object(
|
||||
ExchangeConnectionService,
|
||||
"_validate_tables_exist",
|
||||
) as tables_mock, patch.object(
|
||||
ExchangeConnectionService,
|
||||
"_validate_columns_exist",
|
||||
) as columns_mock:
|
||||
ExchangeConnectionService.validate_target_structure(
|
||||
connection=connection,
|
||||
alias="target_alias",
|
||||
schema_name="public",
|
||||
)
|
||||
|
||||
db_connection.ensure_connection.assert_called_once_with()
|
||||
extend_mock.assert_called_once()
|
||||
@@ -174,19 +176,19 @@ class ExchangeConnectionServiceUnitTest(TestCase):
|
||||
connections_mock = MagicMock()
|
||||
connections_mock.__getitem__.return_value = db_connection
|
||||
|
||||
with patch("apps.exchange.services.connections", connections_mock):
|
||||
with patch.object(
|
||||
ExchangeConnectionService,
|
||||
"_validate_schema_exists",
|
||||
side_effect=ExchangeServiceError("bad schema"),
|
||||
):
|
||||
with self.assertRaisesMessage(ExchangeServiceError, "bad schema"):
|
||||
ExchangeConnectionService.validate_target_structure(
|
||||
connection=connection,
|
||||
alias="target_alias",
|
||||
schema_name="public",
|
||||
models_to_copy=[_FakeModel],
|
||||
)
|
||||
with patch(
|
||||
"apps.exchange.services.connections", connections_mock
|
||||
), patch.object(
|
||||
ExchangeConnectionService,
|
||||
"_validate_schema_exists",
|
||||
side_effect=ExchangeServiceError("bad schema"),
|
||||
), self.assertRaisesMessage(ExchangeServiceError, "bad schema"):
|
||||
ExchangeConnectionService.validate_target_structure(
|
||||
connection=connection,
|
||||
alias="target_alias",
|
||||
schema_name="public",
|
||||
models_to_copy=[_FakeModel],
|
||||
)
|
||||
|
||||
connection.refresh_from_db()
|
||||
self.assertEqual(connection.last_error, "bad schema")
|
||||
@@ -197,22 +199,22 @@ class ExchangeConnectionServiceUnitTest(TestCase):
|
||||
connections_mock = MagicMock()
|
||||
connections_mock.__getitem__.return_value = db_connection
|
||||
|
||||
with patch("apps.exchange.services.connections", connections_mock):
|
||||
with patch.object(
|
||||
ExchangeConnectionService,
|
||||
"_validate_schema_exists",
|
||||
side_effect=RuntimeError("unexpected"),
|
||||
):
|
||||
with self.assertRaisesMessage(
|
||||
ExchangeServiceError,
|
||||
"Ошибка проверки структуры целевой БД: unexpected",
|
||||
):
|
||||
ExchangeConnectionService.validate_target_structure(
|
||||
connection=connection,
|
||||
alias="target_alias",
|
||||
schema_name="public",
|
||||
models_to_copy=[_FakeModel],
|
||||
)
|
||||
with patch(
|
||||
"apps.exchange.services.connections", connections_mock
|
||||
), patch.object(
|
||||
ExchangeConnectionService,
|
||||
"_validate_schema_exists",
|
||||
side_effect=RuntimeError("unexpected"),
|
||||
), self.assertRaisesMessage(
|
||||
ExchangeServiceError,
|
||||
"Ошибка проверки структуры целевой БД: unexpected",
|
||||
):
|
||||
ExchangeConnectionService.validate_target_structure(
|
||||
connection=connection,
|
||||
alias="target_alias",
|
||||
schema_name="public",
|
||||
models_to_copy=[_FakeModel],
|
||||
)
|
||||
|
||||
connection.refresh_from_db()
|
||||
self.assertEqual(connection.last_error, "unexpected")
|
||||
@@ -223,37 +225,34 @@ class ExchangeConnectionServiceUnitTest(TestCase):
|
||||
connections_mock = MagicMock()
|
||||
connections_mock.__getitem__.return_value = db_connection
|
||||
|
||||
with patch("apps.exchange.services.connections", connections_mock):
|
||||
with patch.object(
|
||||
ExchangeConnectionService,
|
||||
"_configure_alias",
|
||||
return_value="target_alias",
|
||||
):
|
||||
with patch.object(
|
||||
ExchangeConnectionService,
|
||||
"_resolve_models",
|
||||
return_value=[_FakeModel, _AnotherFakeModel],
|
||||
):
|
||||
with patch.object(
|
||||
ExchangeConnectionService,
|
||||
"_extend_models_with_dependencies",
|
||||
return_value=[_FakeModel, _AnotherFakeModel],
|
||||
):
|
||||
with patch.object(
|
||||
ExchangeConnectionService,
|
||||
"validate_target_structure",
|
||||
) as validate_mock:
|
||||
with patch.object(
|
||||
ExchangeConnectionService,
|
||||
"_copy_model_data",
|
||||
side_effect=[2, 3],
|
||||
) as copy_mock:
|
||||
result = ExchangeConnectionService.copy_parsers_data(
|
||||
connection=connection,
|
||||
mode="selected",
|
||||
tables=["fake_table", "another_table"],
|
||||
truncate_before_copy=False,
|
||||
)
|
||||
with patch(
|
||||
"apps.exchange.services.connections", connections_mock
|
||||
), patch.object(
|
||||
ExchangeConnectionService,
|
||||
"_configure_alias",
|
||||
return_value="target_alias",
|
||||
), patch.object(
|
||||
ExchangeConnectionService,
|
||||
"_resolve_models",
|
||||
return_value=[_FakeModel, _AnotherFakeModel],
|
||||
), patch.object(
|
||||
ExchangeConnectionService,
|
||||
"_extend_models_with_dependencies",
|
||||
return_value=[_FakeModel, _AnotherFakeModel],
|
||||
), patch.object(
|
||||
ExchangeConnectionService,
|
||||
"validate_target_structure",
|
||||
) as validate_mock, patch.object(
|
||||
ExchangeConnectionService,
|
||||
"_copy_model_data",
|
||||
side_effect=[2, 3],
|
||||
) as copy_mock:
|
||||
result = ExchangeConnectionService.copy_parsers_data(
|
||||
connection=connection,
|
||||
mode="selected",
|
||||
tables=["fake_table", "another_table"],
|
||||
truncate_before_copy=False,
|
||||
)
|
||||
|
||||
self.assertEqual(result["mode"], "selected")
|
||||
self.assertEqual(result["tables"], ["fake_table", "another_table"])
|
||||
@@ -278,36 +277,34 @@ class ExchangeConnectionServiceUnitTest(TestCase):
|
||||
connections_mock = MagicMock()
|
||||
connections_mock.__getitem__.return_value = db_connection
|
||||
|
||||
with patch("apps.exchange.services.connections", connections_mock):
|
||||
with patch.object(
|
||||
ExchangeConnectionService,
|
||||
"_configure_alias",
|
||||
return_value="target_alias",
|
||||
):
|
||||
with patch.object(
|
||||
ExchangeConnectionService,
|
||||
"_resolve_models",
|
||||
return_value=[_FakeModel],
|
||||
):
|
||||
with patch.object(
|
||||
ExchangeConnectionService,
|
||||
"_extend_models_with_dependencies",
|
||||
return_value=[_FakeModel],
|
||||
):
|
||||
with self.assertRaisesMessage(
|
||||
ExchangeServiceError,
|
||||
"Ошибка подключения к целевой БД: target unavailable",
|
||||
):
|
||||
ExchangeConnectionService.copy_parsers_data(
|
||||
connection=connection,
|
||||
mode="all",
|
||||
)
|
||||
with patch(
|
||||
"apps.exchange.services.connections", connections_mock
|
||||
), patch.object(
|
||||
ExchangeConnectionService,
|
||||
"_configure_alias",
|
||||
return_value="target_alias",
|
||||
), patch.object(
|
||||
ExchangeConnectionService,
|
||||
"_resolve_models",
|
||||
return_value=[_FakeModel],
|
||||
), patch.object(
|
||||
ExchangeConnectionService,
|
||||
"_extend_models_with_dependencies",
|
||||
return_value=[_FakeModel],
|
||||
), self.assertRaisesMessage(
|
||||
ExchangeServiceError,
|
||||
"Ошибка подключения к целевой БД: target unavailable",
|
||||
):
|
||||
ExchangeConnectionService.copy_parsers_data(
|
||||
connection=connection,
|
||||
mode="all",
|
||||
)
|
||||
|
||||
connection.refresh_from_db()
|
||||
self.assertEqual(connection.last_error, "target unavailable")
|
||||
|
||||
def test_configure_alias_closes_existing_connection_and_clears_cache(self):
|
||||
connection = ExchangeConnectionFactory(password="secret")
|
||||
connection = ExchangeConnectionFactory(password=_db_secret())
|
||||
alias = f"exchange_target_{connection.id}"
|
||||
existing_db_connection = MagicMock()
|
||||
storage = SimpleNamespace(**{alias: "stale"})
|
||||
@@ -321,7 +318,9 @@ class ExchangeConnectionServiceUnitTest(TestCase):
|
||||
|
||||
self.assertEqual(configured_alias, alias)
|
||||
existing_db_connection.close.assert_called_once_with()
|
||||
self.assertEqual(connections_mock.databases[alias]["NAME"], connection.database_name)
|
||||
self.assertEqual(
|
||||
connections_mock.databases[alias]["NAME"], connection.database_name
|
||||
)
|
||||
self.assertEqual(connections_mock.databases[alias]["PASSWORD"], "secret")
|
||||
self.assertNotIn(alias, storage.__dict__)
|
||||
|
||||
@@ -333,15 +332,16 @@ class ExchangeConnectionServiceUnitTest(TestCase):
|
||||
connections_mock = MagicMock()
|
||||
connections_mock.__getitem__.return_value = db_connection
|
||||
|
||||
with patch("apps.exchange.services.connections", connections_mock):
|
||||
with self.assertRaisesMessage(
|
||||
ExchangeServiceError,
|
||||
"Схема 'public' отсутствует в целевой БД",
|
||||
):
|
||||
ExchangeConnectionService._validate_schema_exists(
|
||||
alias="target_alias",
|
||||
schema_name="public",
|
||||
)
|
||||
with patch(
|
||||
"apps.exchange.services.connections", connections_mock
|
||||
), self.assertRaisesMessage(
|
||||
ExchangeServiceError,
|
||||
"Схема 'public' отсутствует в целевой БД",
|
||||
):
|
||||
ExchangeConnectionService._validate_schema_exists(
|
||||
alias="target_alias",
|
||||
schema_name="public",
|
||||
)
|
||||
|
||||
def test_validate_tables_exist_raises_when_tables_missing(self):
|
||||
cursor = MagicMock()
|
||||
@@ -351,16 +351,17 @@ class ExchangeConnectionServiceUnitTest(TestCase):
|
||||
connections_mock = MagicMock()
|
||||
connections_mock.__getitem__.return_value = db_connection
|
||||
|
||||
with patch("apps.exchange.services.connections", connections_mock):
|
||||
with self.assertRaisesMessage(
|
||||
ExchangeServiceError,
|
||||
"В целевой БД отсутствуют таблицы: another_table",
|
||||
):
|
||||
ExchangeConnectionService._validate_tables_exist(
|
||||
alias="target_alias",
|
||||
schema_name="public",
|
||||
models_to_copy=[_FakeModel, _AnotherFakeModel],
|
||||
)
|
||||
with patch(
|
||||
"apps.exchange.services.connections", connections_mock
|
||||
), self.assertRaisesMessage(
|
||||
ExchangeServiceError,
|
||||
"В целевой БД отсутствуют таблицы: another_table",
|
||||
):
|
||||
ExchangeConnectionService._validate_tables_exist(
|
||||
alias="target_alias",
|
||||
schema_name="public",
|
||||
models_to_copy=[_FakeModel, _AnotherFakeModel],
|
||||
)
|
||||
|
||||
def test_validate_columns_exist_raises_when_columns_missing(self):
|
||||
cursor_context = MagicMock()
|
||||
@@ -372,19 +373,22 @@ class ExchangeConnectionServiceUnitTest(TestCase):
|
||||
connections_mock = MagicMock()
|
||||
connections_mock.__getitem__.return_value = db_connection
|
||||
|
||||
with patch("apps.exchange.services.connections", connections_mock):
|
||||
with self.assertRaisesMessage(
|
||||
ExchangeServiceError,
|
||||
"В таблице 'fake_table' отсутствуют колонки: name",
|
||||
):
|
||||
ExchangeConnectionService._validate_columns_exist(
|
||||
alias="target_alias",
|
||||
schema_name="public",
|
||||
models_to_copy=[_FakeModel],
|
||||
)
|
||||
with patch(
|
||||
"apps.exchange.services.connections", connections_mock
|
||||
), self.assertRaisesMessage(
|
||||
ExchangeServiceError,
|
||||
"В таблице 'fake_table' отсутствуют колонки: name",
|
||||
):
|
||||
ExchangeConnectionService._validate_columns_exist(
|
||||
alias="target_alias",
|
||||
schema_name="public",
|
||||
models_to_copy=[_FakeModel],
|
||||
)
|
||||
|
||||
def test_get_parser_models_uses_configured_labels(self):
|
||||
resolved_models = [_FakeModel for _ in ExchangeConnectionService.PARSER_MODEL_LABELS]
|
||||
resolved_models = [
|
||||
_FakeModel for _ in ExchangeConnectionService.PARSER_MODEL_LABELS
|
||||
]
|
||||
|
||||
with patch(
|
||||
"apps.exchange.services.django_apps.get_model",
|
||||
@@ -417,13 +421,12 @@ class ExchangeConnectionServiceUnitTest(TestCase):
|
||||
ExchangeConnectionService,
|
||||
"_get_parser_models",
|
||||
return_value=[ParserLoadLog],
|
||||
):
|
||||
with self.assertRaisesMessage(ExchangeServiceError, "Неизвестная таблица"):
|
||||
ExchangeConnectionService._resolve_models(
|
||||
mode="single",
|
||||
table="unknown_table",
|
||||
tables=None,
|
||||
)
|
||||
), self.assertRaisesMessage(ExchangeServiceError, "Неизвестная таблица"):
|
||||
ExchangeConnectionService._resolve_models(
|
||||
mode="single",
|
||||
table="unknown_table",
|
||||
tables=None,
|
||||
)
|
||||
|
||||
def test_truncate_tables_executes_in_reverse_order(self):
|
||||
cursor = MagicMock()
|
||||
|
||||
Reference in New Issue
Block a user