Pytest-模拟链式调用

Pytest- mock chained call

我正在尝试在 pytest(和 pytest-mock 包)中模拟链式调用,但由于某些未知的(对我来说)原因它不起作用,这意味着我没有得到从我的模拟中嘲笑 return_value。看起来它创建了 MagicMock 的对象,但没有定义 return_value。我的猜测是它与链式调用有关。

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

这是我的测试:

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]

出于某种原因,mock of self.db.execute().all() 没有 return 任何东西。循环内的代码甚至一次都没有执行。
当我打印 print(result) 时,我得到:

<MagicMock name='get_db.execute().all()' id='140427147903424'>

但看起来 return_value 没有分配给它,所以要么它不是同一个对象,要么值以某种方式被删除。

你的代码调用这个:

self.db.execute().all()

在您的测试中,您将设置为:

session.execute.all.return_value

我认为你应该设置:

session.execute.return_value.all.return_value

因为您的代码 调用 执行,所以您需要在其 return 值上设置模拟。