Reputation: 12022
I am trying to use pytest-mock to mock chained function calls.
@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'
The method update_application
has a chained function call like below
Application.objects(id=a['id']).first()
I have tried mocking the chained calls using below approach but I could not mock.
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'
I could mock Application.objects(id=a['id'])
like below which worked fine.
mocker.patch(
'app.Application.objects',
return_value = list_application
)
Can anyone point me on how to mock chained functions?
Upvotes: 0
Views: 1473
Reputation: 2474
Here is how you could do this - I only changed the 3 code lines dealing with the mock:
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'
It's important to understand that you are mocking the objects
function of the Application
class, like so: mocker.patch('app.Application.objects', new=mock_objects)
.
Then, you need to set the return value: mock_objects.return_value.first.return_value = application
.
The first part mock_objects.return_value
is matching the object returned in Application.objects(id=a['id'])
, then you need to append .first.return_value = application
which matches the return value of .first()
Upvotes: 1