Django Channels Postgres InterfaceError:连接已关闭

时间:2019-01-15 03:58:26

标签: django postgresql pytest python-asyncio django-channels

我似乎无法在这里解决这个问题。我正在按照description in the docs为我的渠道消费者编写测试。我通常会使用Django默认的单元测试,但由于Channels需要使用pytest,因此我正在使用它,但仍希望保持编写测试的类结构。

我在编写类似于unittest的设置方法时遇到了问题,该方法将用于初始化测试属性。我尝试过使用method fixtures的类夹具,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 个答案:

答案 0 :(得分: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不再需要数据库调用,并且可以正常工作