从另一个模块检查芹菜任务状态

时间:2012-03-01 00:23:07

标签: django celery django-celery

我正在尝试测试是否在向django服务器发出请求后启动了芹菜任务。我有这样的事情:

# tasks.py
def add(x, y):
    return x + y

# views.py
def home(request): # respond to request at root url
    tasks.add.delay(1,2)
    return HttpResponse('hello world')

# tests.py
class MyTest(TestCase):
    def test_task_triggered(self):
        self.client.get('/')

        # XXXX HOW TO TEST THAT TASK HAS BEEN TRIGGERED?

如何在单元测试中测试任务是否已启动?显然,我没有直接访问任务ID,否则就是like this would work

更一般地说,如何检测跨功能,类或模块触发的芹菜任务?

感谢您的帮助。

3 个答案:

答案 0 :(得分:2)

您可以使用Mock(单位测试时)。在您的任务上修补delay属性,然后检查模拟的called属性。在您的示例中,尝试类似:

# tests.py
from mock import Mock, patch

class MyTest(TestCase):
    def test_task_triggered(self):
        with patch('views.tasks.add.delay') as patch_mock:
            self.client.get('/')
        self.assertTrue(patch_mock.called)

需要注意的是,一旦你完成了这个,在这个测试用例中实际上不会调用tasks.add,因为我们已经用mock替换了它。这个测试只是断言它被调用(你可以检查patch_mock.call_args_list断言它是用正确的参数调用的)

如果这是一个交易破坏者 - 您希望在一个测试用例中断言正在调用任务,以及该任务的影响/副作用 - 您可以尝试wraps属性{ {1}},可能会有效:

mock

但另一种方式可能更好,因为它更好地隔离了正在测试的东西。

答案 1 :(得分:1)

我发现他们有两种方法可以让我的测试中的任务同步运行

<强> 1。使用CELERY_ALWAYS_EAGER = True。

在测试文件的顶部,您可以像这样设置

from django.conf import settings
settings.CELERY_ALWAYS_EAGER = True

from django.test.client import Client

class MyTest(unittest.TestCase):
    def setUp(self):
        self.client = Client()

    def test_sample(self):
        self.client = client.get('/')

<强> 2。对于芹菜2.5,我使用mock来模拟delay方法

这是我的例子

import mock

def mock_delay(task, *args, **kwargs):
    task.run(args, kwargs)

@mock.patch('celery.app.task.BaseTask.delay', mock_delay)
class MyTest(unittest.TestCase):
    def setUp(self):
        self.client = Client()

    def test_sample(self):
        self.client = client.get('/')

这个解决方案适用于celery2.5.3,但是当我升级到celery3.0.12时,它不再起作用了。

似乎celery2.5.3在class BaseTask模块中将class Task更改为celery.app.task

我将代码修改为@mock.patch('celery.app.task.Task.delay', mock_delay)但无法解决。仍然试图弄清楚

答案 2 :(得分:0)

Celery不允许这种交互,但您可以使用缓存甚至会话来监视它的状态。当然,您需要从外部传递一些ID以进一步获得该值。

但是如果你只需要测试它,你可以使用CELERY_ALWAYS_EAGER设置告诉Celery执行所有任务作为简单的程序,甚至不需要celeryd运行。

相关问题