如何在Python中测试Celery应用程序中的Retry?

时间:2015-06-10 00:21:24

标签: python celery python-mock

我试图测试应用程序是否正在重试。

@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

这是显而易见的,但我不知道该怎么做,否则测试是否正在调用该方法。

3 个答案:

答案 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()