单元测试芹菜中的AsyncResult

时间:2013-06-17 18:20:02

标签: python django unit-testing celery

我正在尝试在Django的单元测试框架中测试一些芹菜功能,但每当我尝试检查AsyncResult时,测试就像从未启动过一样。

我知道这段代码在RabbitMQ的真实环境中工作,所以我只是想知道为什么它在使用测试框架时不起作用。

以下是一个例子:

@override_settings(CELERY_EAGER_PROPAGATES_EXCEPTIONS = True,
                   CELERY_ALWAYS_EAGER = True,
                   BROKER_BACKEND = 'memory',)
def test_celery_do_work(self):
    result = myapp.tasks.celery_do_work.AsyncResult('blat')
    applied_task = myapp.tasks.celery_do_work.apply_async((), task_id='blat')
    applied_task.wait()
    # THIS SUCCEEDS
    self.assertTrue(applied_task.successful())
    # THIS FAILS
    self.assertTrue(result.successful())

使用ALWAYS_EAGER选项是否会禁用AsyncResult功能,因为它正在立即执行?如果是这样,有没有办法能够单元测试AsyncResult状态检查?如果我尝试取出ALWAYS_EAGER选项,测试永远不会运行,所以我不知所措。

谢谢!

1 个答案:

答案 0 :(得分:13)

CELERY_ALWAYS_EAGERTrue时,对apply_async()的调用实际上已替换为apply()。返回的结果是EagerResult,它已包含您的任务结果。

所以,是的,设置ALWAYS_EAGER = True会禁用整个AsyncResult功能。绕过整个异步过程,并且实际上没有任务发送到代理,这就是您无法通过AsyncResult检索结果的原因。

在测试只需要Celery结果的代码路径时使用CELERY_ALWAYS_EAGER = True,并以EagerResultAsyncResult的方式工作。

如果需要,有一种方法可以使用AsyncResultCELERY_ALWAYS_EAGER = False运行测试,但为此,您需要在测试用例中调用任务之前启动工作程序。然后,工作人员将能够执行您的任务,AsyncResult将正常工作。你可以看看django-celery-testworker这似乎就是这样,虽然我没有测试过。