简体   繁体   English

难以理解 Python 的 return_value 在以下示例中模拟 Class

[英]Hard to understand return_value for Python Mock Class in the following example

I had a hard time understanding the choice of using return_value .我很难理解使用return_value的选择。 See the following example看下面的例子

# my_module.py

def query(connection):
    cursor = connection.cursor()
    cursor.execute("SELECT name FROM users WHERE id = 1")
    return cursor.fetchone()[0]
# test_query.py

import pytest
from unittest.mock import Mock

# Import the module containing the function to test
import my_module

def test_query():
    # Set up the mock database connection
    connection = Mock()
    cursor = connection.cursor.return_value
    cursor.fetchone.return_value = ("Alice",)

    # Call the function under test
    result = my_module.query(connection)

    # Assert that the function has the expected behavior
    assert result == "Alice"

My question is in test_query.py , why do I need the first return_value ?我的问题在test_query.py中,为什么我需要第一个return_value It looks like if cursor = connection.cursor.return_value , I can replace the cursor in cursor.fetchone.return_value = ("Alice",) , which then becomes connection.cursor.return_value.fetchone.return_value = ("Alice",) ?看起来如果cursor = connection.cursor.return_value ,我可以替换cursor中的cursor.fetchone.return_value = ("Alice",) ,然后变成connection.cursor.return_value.fetchone.return_value = ("Alice",) Why does this code require two return_value ?为什么这段代码需要两个return_value

Without the first return_value , I received TypeError: 'Mock' object is not subscriptable after running pytest没有第一个return_value ,我收到TypeError: 'Mock' object is not subscriptable after running pytest

The broader question is when should I use return_value ?更广泛的问题是我什么时候应该使用return_value

First lets make sure we understand what Mock is.首先让我们确保我们了解Mock是什么。 You can think of it as an object that's every attribute or function call returns another object of type Mock .您可以将其视为每个属性的 object 或 function 调用返回另一个Mock类型的 object。

from unittest.mock import Mock

m = Mock()
for cls in [m, m.any_attribute, m.any_function("any_param"), m.any_function.return_value]:
    assert isinstance(cls, Mock)

We can easilly implement such behaviour by ourself:我们可以很容易地自己实现这样的行为:

class MyMock:
    def __getattribute__(self, _: str):
        return MyMock()

    def __call__(self, *args, **kwargs):
        return MyMock()

However return_value has a special meaning.然而return_value有特殊的含义。 With return value you ask for (or set by yourself) result of calling specified function. return value您要求(或自己设置)调用指定 function 的结果。

Now, what our goal is?现在,我们的目标是什么? Our goal is to make cursor.fetchone() function return something that is subscriptable (because we ask for first element with [0] ).我们的目标是使cursor.fetchone() function 返回可订阅的内容(因为我们要求第一个元素带有[0] )。 But with such syntax:但是使用这样的语法:

connection.cursor.fetchone.return_value = ("Alice, )

We are mocking result of calling fetchone from connection.cursor , not connection.cursor() .我们是 mocking 从connection.cursor调用fetchone的结果,而不是connection.cursor() It would work fine only if cursor is a property .只有当cursorproperty时,它才能正常工作。

To sum up, whenever you see a function call you use return_value and in case of attributes you don't.总而言之,每当您看到 function 调用时,您都会使用return_value ,如果是属性,则不会。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM