Как я могу использовать тестовый клиент Django в нескольких базах данных с ATOMIC_REQUESTS? - PullRequest
0 голосов
/ 03 февраля 2020

В моем settings.py настроены две базы данных, каждая с ATOMIC_REQUESTS:

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql_psycopg2',
        'NAME': 'lolomg',
        'USER': 'lolomg',
        'PASSWORD': 'password',
        'HOST': 'localhost',
        'PORT': '5432',
        'ATOMIC_REQUESTS': True,
    },

    'analytics': {
        'ENGINE': 'django.db.backends.postgresql_psycopg2',
        'NAME': 'analytics',
        'USER': 'lolomg',
        'PASSWORD': 'password',
        'HOST': 'localhost',
        'PORT': '5432',
        'ATOMIC_REQUESTS': True,
    },
}

Если я затем напишу какие-либо тесты, использующие тестовый клиент Django, например,

from django.test import TestCase

class TestEndpoints(TestCase):

    def test_books(self):
        self.client.get("api/v1/books")

Я получу трассировку и исключение, которое выглядит следующим образом:

======================================================================
FAIL: test_books (lolomg.books.tests.test_api.EndpointsTests)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/home/jordi/vcs/lolomg/lolomg/books/tests/test_api.py", line 6, in test_books
    resp = self.client.get(self.url)
  File "/home/jordi/vcs/lolomg/lib/python3.7/site-packages/django/test/client.py", line 535, in get
    response = super().get(path, data=data, secure=secure, **extra)
  File "/home/jordi/vcs/lolomg/lib/python3.7/site-packages/django/test/client.py", line 347, in get
    **extra,
  File "/home/jordi/vcs/lolomg/lib/python3.7/site-packages/django/test/client.py", line 422, in generic
    return self.request(**r)
  File "/home/jordi/vcs/lolomg/lib/python3.7/site-packages/django/test/client.py", line 503, in request
    raise exc_value
  File "/home/jordi/vcs/lolomg/lib/python3.7/site-packages/django/core/handlers/exception.py", line 34, in inner
    response = get_response(request)
  File "/home/jordi/vcs/lolomg/lib/python3.7/site-packages/django/core/handlers/base.py", line 115, in _get_response
    response = self.process_exception_by_middleware(e, request)
  File "/home/jordi/vcs/lolomg/lib/python3.7/site-packages/django/core/handlers/base.py", line 113, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/usr/lib/python3.7/contextlib.py", line 73, in inner
    with self._recreate_cm():
  File "/home/jordi/vcs/lolomg/lib/python3.7/site-packages/django/db/transaction.py", line 175, in __enter__
    if not connection.get_autocommit():
  File "/home/jordi/vcs/lolomg/lib/python3.7/site-packages/django/db/backends/base/base.py", line 379, in get_autocommit
    self.ensure_connection()
  File "/home/jordi/vcs/lolomg/lib/python3.7/site-packages/django/db/backends/base/base.py", line 217, in ensure_connection
    self.connect()
  File "/home/jordi/vcs/lolomg/lib/python3.7/site-packages/django/test/testcases.py", line 144, in __call__
    raise AssertionError(self.message)

AssertionError: Database connections to 'analytics' are not allowed in this test. Add 'analytics' to lolomg.books.tests.test_api.EndpointsTests.databases to ensure proper test isolation and silence this failure.

Следуя этой трассировке стека, мы видим, что это происходит потому, что тестовый клиент пытается установить sh транзакцию для базы данных analytics из-за установки ATOMIC_REQUESTS. Однако, начиная с Django 2.2, соединения с базами данных, отличные от default, теперь должны быть явно включены в тестах:

https://docs.djangoproject.com/en/3.0/topics/testing/tools/#django .test.TransactionTestCase.databases

Это круто, но я на самом деле не хочу вообще подключиться к базе данных analytics для этого теста. На самом деле, существует всего несколько тестов, которые требуют подключения к этой базе данных, поэтому кажется неправильным даже рассматривать эту базу данных для всех других тестов.

Хотя я мог бы сделать databases = '__all__' для любого класса тестирования, который использует тестовый клиент, это тоже кажется неправильным. Я просто не хочу, чтобы тестовый клиент вообще пытался что-либо делать с базой данных аналитики для большинства тестов.

Так что мне вместо этого делать? Как я могу хранить ATOMIC_REQUESTS в каждой базе данных, но включать базу данных analytics только для тестов, которые действительно в ней нуждаются?

1 Ответ

1 голос
/ 04 февраля 2020

Я до сих пор не очень хорошо знаком с Django 2, но, похоже, что единственный способ добиться этого - отключить параметр ATOMIC_REQUESTS для базы данных analytics в и затем снова включите его в тестах, которые его охватывают.

См. https://docs.djangoproject.com/en/2.2/topics/testing/tools/#overriding -settings

Я не думаю, что это идеально, так как вы будете запускать свои тесты в среде, отличной от той, в которой будет выполняться ваш код, но я не уверен, что есть другой способ - просто включить все базы данных для всех тестов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...