使用补丁在Python中模拟Celery任务调用

Pet*_*ron 5 python mocking celery celery-task python-mock

使用模拟返回值修补Celery任务调用将返回<Mock name='mock().get()' ...>而不是预期return_value定义的mock_task.get.return_value = "value".但是,模拟任务在我的单元测试中正常运行.

这是我修补Celery任务的单元测试:

def test_foo(self):

    mock_task = Mock()
    mock_task.get = Mock(return_value={'success': True})

    print mock_task.get() # outputs {'success': True}

    with patch('app.tasks.my_task.delay', new=mock_task) as mocked_task:
        foo()  # this calls the mocked task with an argument, 'input from foo'
        mock_tasked.assert_called_with('input from foo')  # works
Run Code Online (Sandbox Code Playgroud)

以下是正在测试的功能:

def foo():
    print tasks.my_task.delay  # shows a Mock object, as expected
    # now let's call get() on the mocked task:
    task_result = tasks.my_task.delay('input from foo').get()
    print task_result  # => <Mock name='mock().get()' id='122741648'>
    # unexpectedly, this does not return {'success': True}
    if task_result['success']:
        ...
Run Code Online (Sandbox Code Playgroud)

最后一行加注 TypeError: 'Mock' object has no attribute '__getitem__'

为什么我可以在单元测试中调用mock_task.get(),但调用它会foo返回a <Mock ...>而不是预期的返回值?

and*_*and 7

不幸的是,我对芹菜几乎一无所知,但看起来问题就是嘲弄.

你有:

tasks.my_task.delay('input from foo').get()
Run Code Online (Sandbox Code Playgroud)

patch('app.tasks.my_task.delay', new=mock_task)它成为:

mock_task('input from foo').get()
Run Code Online (Sandbox Code Playgroud)

哪个不一样:

mock_task.get()
Run Code Online (Sandbox Code Playgroud)

您应该将模拟创建更改为:

mock_task().get = Mock(return_value={'success': True})
Run Code Online (Sandbox Code Playgroud)

当您访问现有的Mock属性或调用它时,默认情况下会创建新的Mock实例.所以我们可以稍微简化一下:

mock_task().get.return_value = {'success': True}
Run Code Online (Sandbox Code Playgroud)