I'm trying to mock chained call in pytest
(and pytest-mock
package), but for some unknown (for me) reason it doesn't work which means I don't get mocked return_value
from my mock. It looks like it created object of MagicMock
, but without defined return_value
. My guess is that it's related to chained call.
class DatabaseService():
def __init__(self):
self.db = next(get_db())
self.categories = {}
def save(self, product_id):
if not self.categories:
self._load_existing_categories()
...
[rest of the code]
def _load_existing_categories(self):
# result = self.db.execute(select(Category).order_by(Category.id)).all() <-- This is my original line, but I can't make it working even with simplified version (line below)
result = self.db.execute().all()
for obj in result:
print("Result")
print(obj)
self.categories[obj.Category.name] = obj.Category
Here is my test:
def test_load_from_database(mocker):
session = mocker.patch('src.mysql.get_db')
session.execute.all.return_value = ['1st element', '2nd element']
# I tried also mock it by these ways:
# session = mocker.MagicMock()
# session.session.execute().all().return_value = ['1st element', '2nd element']
# session.get_db.execute().all().return_value = ['1st element', '2nd element']
# session.execute.all = ['1st element', '2nd element']
service = DatabaseService()
service.save = mocker.MagicMock(side_effect=service.save)
service.db = session
service.save(123)
[here will be some assert once I make it working]
For some reason, mock of self.db.execute().all()
doesn't return anything. The code inside loop is not executed even single time.
When I print print(result)
I get:
<MagicMock name='get_db.execute().all()' id='140427147903424'>
But it looks like return_value
is not assigned to it, so either it's not the same object or value is removed somehow.
CodePudding user response:
Your code calls this:
self.db.execute().all()
In your test you are setting this:
session.execute.all.return_value
I think you should set:
session.execute.return_value.all.return_value
because your code calls execute, so you need to set up mocks on its return value.