Django channels group_send not passing the event messages in Test environment
I have a Django Channels consumer receive function like the following:
async def receive(self, text_data=None, bytes_data=None):
## Some other code before
await self.channel_layer.group_send(
self.room_name,
{
'type': 'answered_users_count',
'increment_answer_id': 15,
},
)
The answered_users_count function goes like this:
async def answered_users_count(self, event):
print(event)
increment_answer_id = event['increment_answer_id']
await self.send(
text_data=json.dumps({
'meant_for': 'all',
'type': 'answer_count',
'data': {
'increment_answer_id': increment_answer_id
}
})
)
The whole thing works fine with python manage.py runserver, where the print(event) also prints the following dictionary into the command line:
{'type': 'answered_users_count', 'increment_answer_id': 15}
However, this part of the consumer does not work when it comes to running the unit test that I have written for it. Here's the unit test that I've written for testing the above code:
class SampleConsumerTest(TransactionTestCase):
async def test_channel(self):
communicator = WebsocketCommunicator(application, "/ws/walk/qa_control/12/")
connected, subprotocol = await communicator.connect()
self.assertEqual(connected, True)
await communicator.send_to(json.dumps({
"abc": "xyz"
}))
raw_message = await communicator.receive_from()
message = json.loads(raw_message)
When I run the above test case by using python manage.py test, it fails. I figured out that the cause of this is that the event given as the input to answered_users_count does not carry the field increment_answer_id in the test execution. I got to know about this because the print(event) line in the function answered_users_count in this case wrote this value into the command line:
{'type': 'answered_users_count'}
This signifies that it the event that was passed into the answered_users_count was missing the field increment_answer_id.
However, this part works perfectly fine on python3 manage.py runserver. Here's the full error that I am getting for the failure of the test case:
======================================================================
ERROR: test_channel (walk.tests.test_ws_consumer.QAConsumerTest)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/Users/surajsjain/Documents/CollegeStuff/SoftwareEngineering/back-end/venv/lib/python3.9/site-packages/asgiref/testing.py", line 74, in receive_output
return await self.output_queue.get()
File "/opt/homebrew/Cellar/python@3.9/3.9.7_1/Frameworks/Python.framework/Versions/3.9/lib/python3.9/asyncio/queues.py", line 166, in get
await getter
asyncio.exceptions.CancelledError
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/Users/surajsjain/Documents/CollegeStuff/SoftwareEngineering/back-end/venv/lib/python3.9/site-packages/asgiref/testing.py", line 74, in receive_output
return await self.output_queue.get()
File "/Users/surajsjain/Documents/CollegeStuff/SoftwareEngineering/back-end/venv/lib/python3.9/site-packages/asgiref/timeout.py", line 65, in __aexit__
self._do_exit(exc_type)
File "/Users/surajsjain/Documents/CollegeStuff/SoftwareEngineering/back-end/venv/lib/python3.9/site-packages/asgiref/timeout.py", line 102, in _do_exit
raise asyncio.TimeoutError
asyncio.exceptions.TimeoutError
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/Users/surajsjain/Documents/CollegeStuff/SoftwareEngineering/back-end/venv/lib/python3.9/site-packages/asgiref/sync.py", line 204, in __call__
return call_result.result()
File "/opt/homebrew/Cellar/python@3.9/3.9.7_1/Frameworks/Python.framework/Versions/3.9/lib/python3.9/concurrent/futures/_base.py", line 438, in result
return self.__get_result()
File "/opt/homebrew/Cellar/python@3.9/3.9.7_1/Frameworks/Python.framework/Versions/3.9/lib/python3.9/concurrent/futures/_base.py", line 390, in __get_result
raise self._exception
File "/Users/surajsjain/Documents/CollegeStuff/SoftwareEngineering/back-end/venv/lib/python3.9/site-packages/asgiref/sync.py", line 270, in main_wrap
result = await self.awaitable(*args, **kwargs)
File "/Users/surajsjain/Documents/CollegeStuff/SoftwareEngineering/back-end/walk/tests/test_ws_consumer.py", line 109, in test_channel
raw_message = await communicator.receive_from()
File "/Users/surajsjain/Documents/CollegeStuff/SoftwareEngineering/back-end/venv/lib/python3.9/site-packages/channels/testing/websocket.py", line 72, in receive_from
response = await self.receive_output(timeout)
File "/Users/surajsjain/Documents/CollegeStuff/SoftwareEngineering/back-end/venv/lib/python3.9/site-packages/asgiref/testing.py", line 78, in receive_output
self.future.result()
File "/Users/surajsjain/Documents/CollegeStuff/SoftwareEngineering/back-end/venv/lib/python3.9/site-packages/channels/routing.py", line 71, in __call__
return await application(scope, receive, send)
File "/Users/surajsjain/Documents/CollegeStuff/SoftwareEngineering/back-end/venv/lib/python3.9/site-packages/channels/sessions.py", line 47, in __call__
return await self.inner(dict(scope, cookies=cookies), receive, send)
File "/Users/surajsjain/Documents/CollegeStuff/SoftwareEngineering/back-end/venv/lib/python3.9/site-packages/channels/sessions.py", line 263, in __call__
return await self.inner(wrapper.scope, receive, wrapper.send)
File "/Users/surajsjain/Documents/CollegeStuff/SoftwareEngineering/back-end/venv/lib/python3.9/site-packages/channels/auth.py", line 185, in __call__
return await super().__call__(scope, receive, send)
File "/Users/surajsjain/Documents/CollegeStuff/SoftwareEngineering/back-end/venv/lib/python3.9/site-packages/channels/middleware.py", line 26, in __call__
return await self.inner(scope, receive, send)
File "/Users/surajsjain/Documents/CollegeStuff/SoftwareEngineering/back-end/venv/lib/python3.9/site-packages/channels/routing.py", line 150, in __call__
return await application(
File "/Users/surajsjain/Documents/CollegeStuff/SoftwareEngineering/back-end/venv/lib/python3.9/site-packages/channels/routing.py", line 150, in __call__
return await application(
File "/Users/surajsjain/Documents/CollegeStuff/SoftwareEngineering/back-end/venv/lib/python3.9/site-packages/channels/consumer.py", line 94, in app
return await consumer(scope, receive, send)
File "/Users/surajsjain/Documents/CollegeStuff/SoftwareEngineering/back-end/venv/lib/python3.9/site-packages/channels/consumer.py", line 58, in __call__
await await_many_dispatch(
File "/Users/surajsjain/Documents/CollegeStuff/SoftwareEngineering/back-end/venv/lib/python3.9/site-packages/channels/utils.py", line 51, in await_many_dispatch
await dispatch(result)
File "/Users/surajsjain/Documents/CollegeStuff/SoftwareEngineering/back-end/venv/lib/python3.9/site-packages/channels/consumer.py", line 73, in dispatch
await handler(message)
File "/Users/surajsjain/Documents/CollegeStuff/SoftwareEngineering/back-end/walk/controllers/qa_control_ws_consumer.py", line 152, in answered_users_count
increment_answer_id = event['increment_answer_id']
KeyError: 'increment_answer_id'
----------------------------------------------------------------------
Ran 27 tests in 2.635s
FAILED (errors=1)
Destroying test database for alias 'default'...
For the channel layer, I am using the InMemoryChannelLayer. Here's the settings for it:
CHANNEL_LAYERS = {
'default': {
'BACKEND': 'channels.layers.InMemoryChannelLayer'
}
}
Please help!