我正在尝试测试是否在向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。
更一般地说,如何检测跨功能,类或模块触发的芹菜任务?
感谢您的帮助。
答案 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运行。