Django Channels Postgres InterfaceError: соединение уже закрыто
Я не могу обернуться вокруг этой проблемы. Я пишу тесты для моих потребителей на канале, следуя описанию в документации. Я бы обычно использовал стандартный тест Django по умолчанию, но так как Channels требует использования pytest, я использую его, но все равно хотел бы поддерживать структуру классов написания тестов.
У меня были проблемы с написанием метода настройки, похожего на unittest, который я бы использовал для инициализации тестовых атрибутов. Я пробовал фиксации методов, фиксации классов с использованием autouse = true, но ни одна из них, похоже, не работала, так как я не мог получить доступ к атрибутам экземпляра в тестовых методах. В конце концов я просто решил написать set_up
метод экземпляра и вызовите его вручную для каждого класса. Это то, что я до сих пор:
@pytest.mark.django_db
@pytest.mark.asyncio
class TestChatConsumer(object):
@database_sync_to_async
def set_up(self):
self.user = UserFactory()
self.api_client = APIClientFactory()
self.token = TokenFactory(user=self.user)
self.credentials = {
'AUTHORIZATION': self.token.key,
...
}
self.credentials_params = '&'.join(['{}={}'.format(k, v) for k, v in self.credentials.items()])
self.authless_endpoint = '/api/v1/ws/'
self.endpoint = self.authless_endpoint + '?' + self.credentials_params
async def test_connect_without_credentials(self):
await self.set_up()
communicator = WebsocketCommunicator(application, self.authless_endpoint)
connected, subprotocol = await communicator.connect()
assert not connected
async def test_connect_with_credentials(self):
await self.set_up()
communicator = WebsocketCommunicator(application, self.endpoint)
connected, subprotocol = await communicator.connect()
assert connected
Проблема в том, что я продолжаю получать psycopg2.InterfaceError: connection already closed
когда мой потребитель пытается получить доступ к базе данных в своем коде внутри connect
метод. Оно использует database_sync_to_async
и работает довольно хорошо, когда я вручную тестирую его.
В частности, линия в connect
метод, который вызывает ошибку, выглядит так:
await database_sync_to_async(user.inbox.increment_connections)().
Не уверен, что именно проблема как database_sync_to_async
следует правильно очистить старые соединения, чтобы новые могли быть правильно созданы.
Любая помощь будет очень ценится.
1 ответ
Видимо, я смотрел не в том месте. Проблема была в этой строке:
await database_sync_to_async(user.inbox.increment_connections)()
,
inbox
связанный менеджер, поэтому он пытается получить его до фактического database_sync_to_async
и это терпит неудачу, поскольку это требует вызова БД.
Я пробовал это await database_sync_to_async(user).inbox.increment_connections()
и это не сработало, так как он оборачивает метод, а не атрибут, поэтому я решил использовать prefetch_related
чтобы получить inbox
во время аутентификации. Таким образом user.inbox
больше не требует вызова БД и работает нормально