【发布时间】:2014-04-09 15:09:36
【问题描述】:
我有一个用 Django 编写的 REST API,其端点在发布到芹菜任务时会对其进行排队。响应包含我想用来测试任务是否已创建并获得结果的任务 ID。所以,我想做这样的事情:
def test_async_job():
response = self.client.post("/api/jobs/", some_test_data, format="json")
task_id = response.data['task_id']
result = my_task.AsyncResult(task_id).get()
self.assertEquals(result, ...)
我显然不想让 celery worker 来运行单元测试,我希望以某种方式模拟它。我不能使用 CELERY_ALWAYS_EAGER,因为这似乎完全绕过了代理,阻止我使用 AsyncResult 通过其 ID 获取任务(如 here 所述)。
通过 celery 和 kombu docs,我发现有一个用于单元测试的内存中传输,可以满足我的需求。我尝试覆盖 BROKER_URL 设置以在测试中使用它:
@override_settings(BROKER_URL='memory://')
def test_async_job():
但行为与 ampq 代理相同:它阻塞测试等待结果。知道我应该如何配置此代理以使其在测试中正常工作吗?
【问题讨论】:
-
即使有内存中的代理,你仍然需要一个工人。不幸的是,我认为你想做的事情是不可能的。您要么需要启动一个工作人员来使用您的测试,要么使用 CELERY_ALWAYS_EAGER 同步运行任务(在这种情况下,正如您所发现的,您不会得到 AsyncResult)。
-
为什么需要通过 ID 访问任务?这看起来是单元测试的好候选。为什么不直接测试生成任务的函数,而不是通过 HTTP 进行测试呢?这样您就可以得到与
AsyncResult具有相同API 的EagerResult。 -
如果您使用的是 Python 2,您可以使用 django-supervisor 启动 Celery 进行单元测试(并在代码更改时自动重启)。不幸的是,它与 Python 3 不兼容。(意识到这不是您要的,但万一它对任何人都有用。)