Тесты для потребителей Django Channels: потребителю не отправлено answer_channel

Я использую Django Channels с декоратором @channel_session_user (для доступа к данным сеанса Django).

@channel_session_user_from_http
def ws_connect(message):
    # creates group names like "group-1"
    group_kw = get_group_id_for_user(message.user)
    Group(group_kw).add(message.reply_channel)

@channel_session_user
def ws_receive(message):
    group_kw = get_group_id_for_user(message.user)
    payload = json.loads(message.content['text'])
    Channel(payload['action']).send(message.content)

@channel_session_user
def ws_disconnect(message):
    group_kw = get_group_id_for_user(message.user)
    Group(group_kw).discard(message.reply_channel)

Это работает нормально, но есть проблема при тестировании.

Приведенный ниже тест должен поместить сообщение в канал websocket.receive, затем ws_receive должен взять сообщение и поместить его в канал, указанный в значении action сообщения. Наконец, я проверяю, действительно ли он был размещен на этом канале.

def test_send_chat_message_is_used_by_consumer(self):
    # Make sure a user is authenticated
    self.assertTrue(auth.get_user(self.client).is_authenticated())

    payload = {'action': 'chat.receive',
               'msg': 'Test message.',
               'receiver': self.user2.id}
    message = {'text': json.dumps(payload)}

    # Send a chat message
    Channel('websocket.receive').send(message)
    # Receive it and place it on the right channel
    ws_receive(self.get_next_message('websocket.receive', require=True))
    # Fetch it from the channel
    result = self.get_next_message(payload['action'], require=True)
    # That should be the message sent
    self.assertEqual(result, message)

Вместо этого я получаю следующую ошибку, указывающую на строку с вызовом ws_receive().

ValueError: ответ_канала не отправлен потребителю; @channel_session можно использовать только в сообщениях, содержащих его.

Ошибка возникает здесь в каналах источник.

Печать reply_channel возвращает None вместо того, чтобы содержать правильное имя канала ответа.

tmp = self.get_next_message('websocket.receive', require=True)
print(tmp.reply_channel)  # prints: None

Я упускаю из виду что-то очевидное?


person C14L    schedule 15.08.2016    source источник


Ответы (2)


Я думаю, что вы не можете просто вызвать потребителя, потому что у него есть декоратор @channel_session_user. Вам следует попробовать использовать клиентские каналы. Тесты предоставляют.

from channels.tests import ChannelTestCase, Client

Затем используйте что-то подобное внутри тестовой функции

client = Client()
client.send('websocket.receive', content=message)
person Doge    schedule 19.10.2016

Это связано с тем, что имя, которое вы предоставляете объекту «Канал», представляет собой канал, по которому было получено это сообщение. Проверьте функцию init канала.

Также обратите внимание на функцию get_next_message в тестах/ файл base.py. Параметр channel здесь относится к (ответному) каналу, на который сообщение было отправлено во время теста.

Чтобы ответить на ваш вопрос -

Посмотрите на строку документа объекта сообщения в каналах/ сообщение.py. Он говорит,

Содержимое сообщения представляет собой словарь с именем .content, а answer_channel — необязательный дополнительный атрибут, представляющий канал, который можно использовать для ответа конечному пользователю этого сообщения, если это имеет смысл.

Вам нужно установить «reply_channel» в отправляемом вами диктофоне.

message = {
    'text': json.dumps(payload),
    'reply_channel': 'websocket.receive'
}

Надеюсь, поможет

person akashrajkn    schedule 14.12.2016