模拟 python 中 class 的 属性 的属性

Mock an attribute of a property of a class in python

我在模拟 属性 属性 class 时遇到问题].

我有以下 class:

import boto3

class QueryFetcher:
    def __init__(self, query: str):
        self._query = query
        self._athena = boto3.client("athena")
    
    @property
    def athena(self):
        return self._athena
    
    def query_athena(self):
        # need to mock start_query_execution function
        execution = self._athena.start_query_execution(. . .)
        execution_id = execution["QueryExecutionId"]

        while True:
            # need to mock get_query_execution function
            stats = self._athena.get_query_execution(QueryExecutionId=execution_id)
            . . .

        return status, execution_id

我必须模拟 start_query_executionget_query_execution 函数,它们是 class.

中 属性 athena 的一部分

我正在尝试对函数 query_athena 进行单元测试。这是单元测试的示例文件:

import pytest
from query_fetcher import QueryFetcher
from unittest.mock import patch, PropertyMock


@pytest.fixture
def fetcher_user():
    return QueryFetcher(query="")


@mock.patch(
    "query_fetcher.QueryFetcher.athena",
    new_callable=mock.PropertyMock,
)
def test_query_athena(mock_athena, fetcher_user):
    mock_athena.return_value.get_query_execution.return_value = {
        "QueryExecution": {"Status": {"State": "SUCCEEDED"}}
    }
    mock_athena.return_value.start_query_execution.return_value = {
        "QueryExecutionId": "69320478-2452-465e-bc0d-89cdc8bd4428"
    }
    fetcher_user.query_athena()

但是,这不起作用,我认为这是因为我必须创建 class 的新实例。然后我尝试了以下操作:

@mock.patch(
    "query_fetcher.QueryFetcher.athena",
    new_callable=mock.PropertyMock,
)
def test_query_athena(mock_athena):
    mock_athena.return_value.get_query_execution.return_value = {
        "QueryExecution": {"Status": {"State": "SUCCEEDED"}}
    }
    mock_athena.return_value.start_query_execution.return_value = {
        "QueryExecutionId": "69320478-2452-465e-bc0d-89cdc8bd4428"
    }
    # create a new class instance
    fetcher_user = QueryFetcher(query="")
    fetcher_user.query_athena()

但这也不管用。我在这里错过了什么?

理想情况下,我想在我的装置 fetcher_user 上模拟 属性 athena,而不是完全创建一个新实例。我也不想修改我的夹具来模拟夹具内的功能。这可能吗?

如果能就此问题提供帮助,我将不胜感激!

我通过执行以下操作解决了这个问题:

import mock

def test_query_athena(fetcher_user):
    fetcher_user._athena = mock.MagicMock()
    fetcher_user._athena.get_query_execution.return_value = {"QueryExecution": {"Status": {"State": "SUCCEEDED"}}}
    fetcher_user._athena.start_query_execution.return_value = {"QueryExecutionId": "69320478-2452-465e-bc0d-89cdc8bd4428"}
    fetcher_user.query_athena()

这也根据我的需要使用了固定装置并使事情变得简单:)