Closed cobalamin closed 2 years ago
I'm experiencing the same issue.
I'm using django channels, pytest-django, and pytest-asyncio to run some websocket tests. Since introducing these tests, the teardown fails.
almost the same issue, happens always, but
the connection is closed
diagnostic, please resolve
_________________________________________________________________________________________________________________ test_ping _________________________________________________________________________________________________________________
self = <django.contrib.gis.db.backends.postgis.base.DatabaseWrapper object at 0x7ff84fc25e10>, name = None
def _cursor(self, name=None):
self.ensure_connection()
with self.wrap_database_errors:
> return self._prepare_cursor(self.create_cursor(name))
../py3.6/lib/python3.6/site-packages/django/db/backends/base/base.py:234:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <django.contrib.gis.db.backends.postgis.base.DatabaseWrapper object at 0x7ff84fc25e10>, name = None
def create_cursor(self, name=None):
if name:
# In autocommit mode, the cursor will be used outside of a
# transaction, hence use a holdable cursor.
cursor = self.connection.cursor(name, scrollable=False, withhold=self.connection.autocommit)
else:
> cursor = self.connection.cursor()
E psycopg2.InterfaceError: connection already closed
../py3.6/lib/python3.6/site-packages/django/db/backends/postgresql/base.py:212: InterfaceError
The above exception was the direct cause of the following exception:
@pytest.mark.asyncio
@pytest.mark.django_db
async def test_ping():
"""Test for proper connection and ping"""
settings.AVOID_WEBSOCKET_AUTHORIZATION = True
User.objects.create(username='test', is_superuser=True, is_active=True)
communicator = WebsocketCommunicator(application, '/simulation_event/')
> connected, subprotocol = await communicator.connect()
simulation/tests/test_consumers.py:26:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
../py3.6/lib/python3.6/site-packages/channels/testing/websocket.py:36: in connect
response = await self.receive_output(timeout)
../py3.6/lib/python3.6/site-packages/asgiref/testing.py:80: in receive_output
self.future.result()
../py3.6/lib/python3.6/site-packages/asgiref/compatibility.py:33: in new_application
instance = application(scope)
../py3.6/lib/python3.6/site-packages/channels/routing.py:58: in __call__
return self.application_mapping[scope["type"]](scope)
simulation/consumers.py:49: in __call__
user = User.objects.filter(is_superuser=True, is_active=True).first()
../py3.6/lib/python3.6/site-packages/django/db/models/query.py:604: in first
for obj in (self if self.ordered else self.order_by('pk'))[:1]:
../py3.6/lib/python3.6/site-packages/django/db/models/query.py:272: in __iter__
self._fetch_all()
../py3.6/lib/python3.6/site-packages/django/db/models/query.py:1179: in _fetch_all
self._result_cache = list(self._iterable_class(self))
../py3.6/lib/python3.6/site-packages/django/db/models/query.py:54: in __iter__
results = compiler.execute_sql(chunked_fetch=self.chunked_fetch, chunk_size=self.chunk_size)
../py3.6/lib/python3.6/site-packages/django/db/models/sql/compiler.py:1061: in execute_sql
cursor = self.connection.cursor()
../py3.6/lib/python3.6/site-packages/django/db/backends/base/base.py:255: in cursor
return self._cursor()
../py3.6/lib/python3.6/site-packages/django/db/backends/base/base.py:234: in _cursor
return self._prepare_cursor(self.create_cursor(name))
../py3.6/lib/python3.6/site-packages/django/db/utils.py:89: in __exit__
raise dj_exc_value.with_traceback(traceback) from exc_value
../py3.6/lib/python3.6/site-packages/django/db/backends/base/base.py:234: in _cursor
return self._prepare_cursor(self.create_cursor(name))
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <django.contrib.gis.db.backends.postgis.base.DatabaseWrapper object at 0x7ff84fc25e10>, name = None
def create_cursor(self, name=None):
if name:
# In autocommit mode, the cursor will be used outside of a
# transaction, hence use a holdable cursor.
cursor = self.connection.cursor(name, scrollable=False, withhold=self.connection.autocommit)
else:
> cursor = self.connection.cursor()
E django.db.utils.InterfaceError: connection already closed
../py3.6/lib/python3.6/site-packages/django/db/backends/postgresql/base.py:212: InterfaceError
If someone can create a minimal test case for me to easily install and run (maybe in a dummy github project), I can take a look.
@Tinche sorry, looks like my case is not caused by your package
I am using django-channels and have setup a test for my websocket consumer using pytest-asyncio and pytest-django.
The websocket tests rely on some models being present in the database.
I am using channels.db.database_sync_to_async
to decorate all code that creates models for the tests, and this seems to work ok. Note I am using postgres .
For example
@database_sync_to_async
def create_model():
model = MyModel.objects.create(name="test")
return model.id
@pytest.mark.asyncio
@pytest.mark.django_db
async def test_consumer():
model_id = await create_model()
communicator = WebsocketCommunicator(
url_router,
f'/model_url/{model_id}/',
)
connected, subprotocol = await communicator.connect()
assert connected
# Close
await communicator.disconnect()
All participants in this issue could either resolve their problem or didn't provide additional information. I don't think there's much we can about this without a reproducible example.
Cross-referencing this issue with #226 which describes problems with database transaction rollback in Django. The discussion there points to issues in pytest-django and async tests in Django.
I'm closing this issue. Feel free to reopen it, if the problem persists.
We have a project in which we're trying to test websockets via Django Channels. The tests we wrote also involve using the Django ORM to create some objects in the database. The test thus uses both the
asyncio
anddjango_db
mark (with thetransaction
option set to True, since we want each test to run in a clean DB).When running our test suite (or just this test on its own), the tests sometimes succeed, and sometimes fail with an error message like below, indicating that there's an open connection and the test database cannot be dropped, which makes the entire test run fail. (This failure always occurs some time after the last test in the suite completes, no matter what that specific test is.)
Further info: We're using
django.contrib.gis.db.backends.postgis
as the DB backend, also for tests.