如何在 pytest-mock 中模拟链式调用

How to mock chained calls in pytest-mock

我正在尝试使用 pytest-mock 模拟链式函数调用。

@app.route('/application', methods=['PUT'])
    def update_application():
        a = json.loads(request.data)['application']
        application = Application.objects(id=a['id']).first()
        if not application:
            return jsonify({'error': 'data not found'})
        else:
            application.update(jobTitle=a['jobTitle'],
                                companyName=a['companyName'],
                                date=a['date'],
                                status=a['status'

方法 update_application 有一个链式函数调用,如下所示

Application.objects(id=a['id']).first()

我尝试使用以下方法模拟链接调用,但我无法模拟。

def test_update_application(client, mocker):
    application = Application(id=4, jobTitle='fakeJob12345', companyName='fakeCompany', date=str(datetime.date(2021, 9, 22)))
    mocker.patch(
        'app.Application.update'
    )
    m = mocker.MagicMock()
    m.Application.objects().first.return_value = application
    rv = client.put('/application', json={'application':{
        'id':2, 'jobTitle':'fakeJob12345', 'companyName':'fakeCompany', 'date':str(datetime.date(2021, 9, 23)), 'status':'1'
        }})
    print(rv.data)
    jdata = json.loads(rv.data.decode("utf-8"))["jobTitle"]
    assert jdata == 'fakeJob12345' 

我可以像下面那样模拟 Application.objects(id=a['id']),效果很好。

mocker.patch(
        'app.Application.objects',
        return_value = list_application
    )

谁能告诉我如何模拟链式函数?

你可以这样做 - 我只更改了处理模拟的 3 行代码:

def test_update_application(client, mocker):
    application = Application(id=4, jobTitle='fakeJob12345', companyName='fakeCompany', date=str(datetime.date(2021, 9, 22)))

    mock_objects = mocker.MagicMock(name='objects')
    mocker.patch('app.Application.objects', new=mock_objects)
    mock_objects.return_value.first.return_value = application

    rv = client.put('/application', json={'application':{
        'id':2, 'jobTitle':'fakeJob12345', 'companyName':'fakeCompany', 'date':str(datetime.date(2021, 9, 23)), 'status':'1'
        }})
    print(rv.data)
    jdata = json.loads(rv.data.decode("utf-8"))["jobTitle"]
    assert jdata == 'fakeJob12345'

了解您正在模拟 Application class 的 objects 函数很重要,就像这样:mocker.patch('app.Application.objects', new=mock_objects).

然后,您需要设置return值:mock_objects.return_value.first.return_value = application.

第一部分mock_objects.return_value匹配Application.objects(id=a['id'])中的对象return,然后你需要追加.first.return_value = application匹配的return值.first()