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 больше не требует вызова БД и работает нормально

Другие вопросы по тегам