我试图测试应用程序是否正在重试。
@celery.task(bind=False, default_retry_delay=30)
def convert_video(gif_url, webhook):
// doing something
VideoManager().convert(gif_url)
return
except Exception as exc:
raise convert_video.retry(exc=exc)
我嘲笑测试
@patch('src.video_manager.VideoManager.convert')
@patch('requests.post')
def test_retry_failed_task(self, mock_video_manager, mock_requests):
mock_video_manager.return_value= {'webm':'file.webm', 'mp4':'file.mp4', 'ogv' : 'file.ogv', 'snapshot':'snapshot.png'}
mock_video_manager.side_effect = Exception('some error')
server.convert_video.retry = MagicMock()
server.convert_video('gif_url', 'http://www.company.com/webhook?attachment_id=1234')
server.convert_video.retry.assert_called_with(ANY)
我收到此错误
TypeError:异常必须是旧式类或派生自BaseException,而不是MagicMock
这是显而易见的,但我不知道该怎么做,否则测试是否正在调用该方法。
答案 0 :(得分:3)
我还没有使用内置的重试工作,所以我必须使用带有真实重试副作用的模拟,这样就可以在测试中捕获它。 我已经这样做了:
from celery.exceptions import Retry
from mock import MagicMock
from nose.plugins.attrib import attr
# Set it for for every task-call (or per task below with @patch)
task.retry = MagicMock(side_effect=Retry)
#@patch('task.retry', MagicMock(side_effect=Retry)
def test_task(self):
with assert_raises(Retry):
task() # Note, no delay or things like that
# and the task, I don't know if it works without bind.
@Celery.task(bind=True)
def task(self):
raise self.retry()
如果有人知道如何摆脱嘲笑重试"例外"我很高兴听到它!
答案 1 :(得分:2)
from mock import patch
import pytest
@patch('tasks.convert_video.retry')
@patch('tasks.VideoManager')
def test_retry_on_exception(mock_video_manger, mock_retry):
mock_video_manger.convert.side_effect = error = Exception()
with pytest.raises(Exception):
tasks.convert_video('foo', 'bar')
mock_retry.assert_called_with(exc=error)
你也错过了任务中的一些东西:
@celery.task(bind=False, default_retry_delay=30)
def convert_video(gif_url, webhook):
try:
return VideoManager().convert(gif_url)
except Exception as exc:
convert_video.retry(exc=exc)
答案 2 :(得分:0)
这里的答案并没有帮助我,所以我更深入地研究了celery's code,发现了一个对我有用的黑客:
def test_celery_retry(monkeypatch):
# so the retry will be eager
monkeypatch.setattr(celery_app.conf, 'task_always_eager', True)
# so celery won't try to raise an error and actually retry
monkeypatch.setattr(celery.app.task.Context, 'called_directly', False)
task.delay()