我正在尝试在我的Django应用程序中为一些芹菜任务编写一些单元测试。这些任务将模型ID作为参数,执行一些操作并更新模型。当运行devserver和celery worker时,一切都很好,但是在运行我的测试时,很明显celery任务没有使用在测试运行过程中创建和销毁的django测试数据库。问题是,如何让芹菜使用与我的其他测试相同的临时数据库?
正如您所看到的,我正在使用针对类似问题的每个答案中建议的设置覆盖。
更新:发现不是将对象id传递给任务而是让任务从数据库中获取,如果我只是将对象本身传递给任务,那么测试工作正常,显然没有对任务产生负面影响。任务。所以至少现在,这将是我的修复。
在我的测试中:
class JobTest(TestCase):
@override_settings(CELERY_ALWAYS_EAGER=True,
CELERY_EAGER_PROPAGATES_EXCEPTIONS=True,
BROKER_BACKEND='memory')
def test_Job_Complete(self):
job = models.Job()
job.save()
tasks.do_a_thing(job.id)
self.assertTrue(job.complete)
在我的任务中:
@celery.task
def do_a_thing(job_id):
job = models.Job.objects.get(pk=job_id)
bunch_of_things(job)
job.complete = True
job.save()
答案 0 :(得分:2)
我遇到了类似的问题。以下解决方案是不干净,但它有效。
integration_testing.py
。您的文件应如下所示:
from .settings import *
DATABASES = {
'default': {
'ENGINE': '<your engine>',
'NAME': 'test_<your database name>',
'USER': <your db user>,
'PASSWORD': <your db password>,
'HOST': <your hostname>,
'PORT': <your port number>,
}
创建一个shell脚本,用于设置环境并启动 芹菜工人:
#!/usr/bin/env bash
export DJANGO_SETTINGS_MODULE="YOURPROJECTNAME.settings.integration_testing"
celery purge -A YOURPROJECTNAME -f && celery worker -A YOURPROJECTNAME -l debug
如果您以这种方式配置芹菜,则上述情况有效:
app = Celery('YOURPROJECTNAME')
app.config_from_object('django.conf:settings', namespace='CELERY')
在后台运行脚本。
让所有涉及Celery的测试都继承自TransactionTestCase(或django-rest-framework中的APITransactionTestCase)
运行使用芹菜的单元测试。任何芹菜任务现在都将使用您的测试数据库。并希望最好。
答案 1 :(得分:1)
您的代码没有明显问题。你不需要经营芹菜工人。通过这些设置,芹菜将同步运行任务,并且实际上不会向您的消息队列发送任何内容。
无论如何,您无法轻松地使用实时芹菜工作者运行测试,因为每个测试都包含在一个事务中,因此即使它们连接到同一个数据库(它们不是),事务总是会被测试和从来没有给工人。
如果您确实需要这样做,请查看this stackoverflow answer。
答案 2 :(得分:1)
保证Celery工作程序配置为使用与测试相同的测试数据库的一种方法是spawn the Celery worker inside the test itself。这可以通过在celery.contrib.testing.worker.start_worker
的{{1}}方法中使用setUpClass
来完成。
您还必须使用来自Django的TestCase
或来自Rest的SimpleTestCase
而不是普通APISimpleTestCase
,以便Celery线程和测试线程可以看到彼此的更改制作测试数据库。这些更改在测试结束时仍然被销毁,但除非您在TestCase
方法中手动销毁它们,否则它们不会在测试之间销毁。
答案 3 :(得分:0)
我发现将以下内容添加到 conftest.py
有效:
from django.conf import settings
...
@pytest.fixture(scope="session")
def celery_worker_parameters(django_db_setup):
assert settings.DATABASES["default"]["NAME"].startswith("test_")
return {}
诀窍是在此处添加 django_db_setup
固定装置,以便在工作器上启用它。
这是对标有以下标记的测试的测试:
@pytest.mark.django_db(transaction=True)
@pytest.mark.celery()
def test_something(celery_worker):
...