django-channels - 使用 pytest 进行 Django 通道 ProtocolTypeRouter 单元测试
问题描述
我正在检查下一个项目的频道。但我坚持对基础进行单元测试。我想这一定是我一直忽略的东西。
版本:
- 频道==2.1.7
- django==2.1.3
路由.py
from channels.routing import ProtocolTypeRouter #, URLRouter
from Phoenix.ProtocolTestConsumer import ProtocolTestConsumer
application = ProtocolTypeRouter({
# Empty for now (http->django views is added by default)
"test": ProtocolTestConsumer,
})
协议测试消费者.py
import logging
logging.basicConfig(level=logging.DEBUG)
from django.conf import settings
from channels.consumer import SyncConsumer
class ProtocolTestConsumer(SyncConsumer):
def test_a(self, event):
logging.debug("consumer test_a {}".format(event))
def test_b(self, event):
logging.debug("consumer test_b {}".format(event))
def test_c(self, event):
logging.debug("consumer test_c {}".format(event))
test_ProtocolTestConsumer.py
import pytest
import logging
from Phoenix.ProtocolTestConsumer import ProtocolTestConsumer
from channels.testing import ApplicationCommunicator
communicator = ApplicationCommunicator(ProtocolTestConsumer, {"type": "test"})
@pytest.mark.asyncio
async def test_call_a():
await communicator.send_input(
{"type": "test.a",
"text": "Blue"})
logging.debug("pytest is printing this")
DJANGO_SETTINGS_MODULE=web.settings pytest -s -v
== test session starts ==
platform linux -- Python 3.7.1, pytest-4.1.1, py-1.7.0, pluggy-0.8.1 -- /home/user/src/web/Phoenix/venv-phoenix/bin/python3.7
cachedir: .pytest_cache
Django settings: web.settings (from environment variable)
rootdir: /home/user/src/web/Phoenix/web/Phoenix, inifile:
plugins: django-3.4.5, asyncio-0.10.0
collected 1 item
test_ProtocolTestConsumer.py::test_call_a DEBUG:asyncio:Using selector: EpollSelector
DEBUG:root:pytest is printing this
PASSED
== 1 passed in 0.24 seconds ==
我希望看到来自消费者的更多控制台输出。
解决方案
我在您的代码中看到了两个问题。首先,您的路由似乎缺少某些部分。在将消费者传递给协议类型路由器之前,应首先将消费者包装为 django url。像这样:
from channels.routing import ProtocolTypeRouter, URLRouter
application = ProtocolTypeRouter({
# Empty for now (http->django views is added by default)
"test": [
path('test/', ProtocolTestConsumer)
]
})
第一个“测试”是做一个协议路由,而第二个是做一个普通的 django url 路由。
其次,在初始化你的通信器时,你应该使用消费者的 url:
ApplicationCommunicator(ProtocolTestConsumer, "test/")
编辑
仔细查看您的代码后,我发现它实际上是正确实现的,只是在较低级别上使其成为自己的协议,如 websocket 和 HTTP。但是,您的错误是在调用send_output
. send_output 调用只是将消息放入队列中。然后receive_output
检索队列顶部的第一条消息,该消息触发对消费者中相应方法的调用。
因此,您需要以这种方式在测试代码中接收输出:
@pytest.mark.asyncio
async def test_call_a():
await communicator.send_input(
{"type": "test.a",
"text": "Blue"})
logging.debug("pytest is printing this")
response = await communicator.receive_output()
您可以查看 的实现WebsocketCommunicator
以及HttpCommunicator
有关它们如何发送和接收消息的更多详细信息
推荐阅读
- laravel - 每次调用函数时如何更新laravel控制器中变量的值
- python - 尝试从数组中打印特定项目,这是“PBCM,Compact”,但目前无法打印,请参阅下面的错误详细信息
- c# - 获取总是返回 null
- python - 如何在's'路径中解开numpy数组?
- python - 如何在 ruby 中进行图像处理?Ruby 中没有 OpenCv?
- javascript - 单击按钮时,按 ID 转到下一个问题
- java - 带有敏感信息的spring boot外部配置不起作用
- go - 从 float64 获取 Alpha 值
- python - 如何使用矩阵分解推荐系统为项目获得推荐用户?
- python-3.x - 为什么即使在 python 中进行垃圾收集后我也能够访问元素?