I am testing my Chat application built with Django Channels and I am trying to create 2 communicators to model 2 users, but I keep getting psycopg2.InterfaceError: connection already closed
in the line where I am instantiating the second communicator. Here's what I have:
async def test_chat(self):
await self.set_up()
communicator = WebsocketCommunicator(application, self.endpoint)
await communicator.connect()
await communicator.receive_from()
communicator2 = WebsocketCommunicator(application, self.endpoint2)
await communicator2.connect()
await communicator2.receive_from()
It works fine with just one communicator, but I need 2 to properly test it. Isn't this possible or am I missing something?
This is what the stacktrace looks like.
> communicator2 = WebsocketCommunicator(application, self.endpoint2)
test_consumers.py:282:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
/home/kenneth/.virtualenvs/weout/lib/python3.6/site-packages/channels/testing/websocket.py:26: in __init__
super().__init__(application, self.scope)
/home/kenneth/.virtualenvs/weout/lib/python3.6/site-packages/asgiref/testing.py:17: in __init__
self.instance = self.application(scope)
/home/kenneth/.virtualenvs/weout/lib/python3.6/site-packages/channels/routing.py:58: in __call__
return self.application_mapping[scope["type"]](scope)
/home/kenneth/.virtualenvs/weout/lib/python3.6/site-packages/channels/security/websocket.py:37: in __call__
return self.application(scope)
../../weout/messaging/authentication.py:40: in __call__
user_auth_tuple = authenticator.authenticate(request)
../../weout/accounts/authentication.py:44: in authenticate
self.authenticate_client(request)
../../weout/accounts/authentication.py:90: in authenticate_client
client = self.client_model.objects.get(client_id=client_id, client_secret=client_secret)
/home/kenneth/.virtualenvs/weout/lib/python3.6/site-packages/django/db/models/manager.py:82: in manager_method
return getattr(self.get_queryset(), name)(*args, **kwargs)
/home/kenneth/.virtualenvs/weout/lib/python3.6/site-packages/django/db/models/query.py:397: in get
num = len(clone)
/home/kenneth/.virtualenvs/weout/lib/python3.6/site-packages/django/db/models/query.py:254: in __len__
self._fetch_all()
/home/kenneth/.virtualenvs/weout/lib/python3.6/site-packages/django/db/models/query.py:1179: in _fetch_all
self._result_cache = list(self._iterable_class(self))
/home/kenneth/.virtualenvs/weout/lib/python3.6/site-packages/django/db/models/query.py:53: in __iter__
results = compiler.execute_sql(chunked_fetch=self.chunked_fetch, chunk_size=self.chunk_size)
/home/kenneth/.virtualenvs/weout/lib/python3.6/site-packages/django/db/models/sql/compiler.py:1066: in execute_sql
cursor = self.connection.cursor()
/home/kenneth/.virtualenvs/weout/lib/python3.6/site-packages/django/db/backends/base/base.py:255: in cursor
return self._cursor()
/home/kenneth/.virtualenvs/weout/lib/python3.6/site-packages/django/db/backends/base/base.py:234: in _cursor
return self._prepare_cursor(self.create_cursor(name))
/home/kenneth/.virtualenvs/weout/lib/python3.6/site-packages/django/db/utils.py:89: in __exit__
raise dj_exc_value.with_traceback(traceback) from exc_value
/home/kenneth/.virtualenvs/weout/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 0x7faa17c7eef0>
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
Basically, it gets to the point where my authenticator is called and tries to make a DB call. As can be seen from the stacktrace, it starts from the line where I instantiate the second communicator.
communicator2 = WebsocketCommunicator(application, self.endpoint2)
Instantiating the first communicator however doesn't give such errors
Adding
transaction=True
to thepytest.mark.django_db
fixture solved the issue. For some reason I never gave that much thought