为什么我的模拟未对以下补丁函数返回True?

0 投票
2 回答
28 浏览
提问于 2025-04-12 22:27

在我的 get_orders.py 文件中,我导入了一个叫 admin_only 的函数,这个函数在指定的路径下(src.lib.authorization)。在我的 test_get_orders.py 文件里,我想要对这个函数进行“修补”,但是这个函数没有被修补。当我运行 pytest 时,它试图调用这个函数的实际代码,而不是返回 True。这是为什么呢?我该怎么解决这个问题?另外,还要提到的是,get_orders.py 文件位于 src/routes/get_orders.py 这个路径下。

# get_orders.py

import boto3
import os
from fastapi import APIRouter, Depends
from aws_lambda_powertools import Logger
from fastapi.exceptions import HTTPException
from src.models import Order
from src.lib.dynamodb import DynamoConnection
from src.lib.response import fastapi_gateway_response
from src.lib.authorization import admin_only

logger = Logger()
router = APIRouter()

orders_table = DynamoConnection(
    os.environ.get("DYNAMODB_REGION", "us-east-1"),
    os.environ.get("DYNAMODB_ENDPOINT_URL", None),
    os.environ.get("DYNAMODB_ORDERS_TABLE_NAME", "orders"),
).table


@logger.inject_lambda_context
@router.get(
    "/orders",
    status_code=200,
    dependencies=[Depends(admin_only)],
)
def get_orders():
    logger.info(f"Getting orders")

    dynamo_response = orders_table.scan()

    if "Items" not in dynamo_response:
        raise HTTPException(status_code=404, detail="No orders found")

    orders = [Order(**o).clean() for o in dynamo_response.get("Items")]

    logger.info(f"Returning {len(orders)} orders")
    return fastapi_gateway_response(200, {}, orders)
#test_get_orders.py

import pytest
import logging
from unittest.mock import patch
from freezegun import freeze_time
from botocore.stub import Stubber
from fastapi.testclient import TestClient
from src.api import app
from src.routes.get_orders import orders_table

logger = logging.getLogger()
test_client = TestClient(app, headers={"Authorization": "Bearer TOKEN"})


@pytest.fixture(autouse=True, scope="function")
def orders_dynamodb_stub():
    with Stubber(orders_table.meta.client) as ddb_stubber:
        yield ddb_stubber
        ddb_stubber.assert_no_pending_responses()


@freeze_time("2024-03-22 12:00:00")
@patch("src.routes.get_orders.admin_only", return_value=True)
def test_handler_valid_event_get_orders(orders_dynamodb_stub):
    orders_dynamodb_stub.add_response(
        "scan",
        {
            "Items": [
                {
                    "order_id": {"S": "ORDER-1"},
                    "dessert_id": {"S": "DESSERT-1"},
                    "dessert_name": {"S": "Chocolate Cake"},
                    "quantity": {"N": "1"},
                    "customer_first_name": {"S": "jane"},
                    "customer_last_name": {"S": "doe"},
                    "customer_email": {"S": "jane.doe@gmail.com"},
                    "customer_phone_number": {"S": "555-555-5555"},
                    "customer_zip_code": {"S": "90210"},
                    "delivery_address": {"S": "123 Main St, Los Angeles, CA 90210"},
                    "scheduled_delivery_time": {"N": "1711108800"},
                    "order_total": {"N": "10.00"},
                    "order_status": {"S": "NEW"},
                    "order_date": {"N": "1711108800"},
                },
            ],
        },
        expected_params={"TableName": "orders"},
    )

    response = test_client.get("/v1/orders")

    pytest.helpers.assert_responses_equal(
        response,
        200,
        [
            {
                "order_id": "ORDER-1",
                "dessert_id": "DESSERT-1",
                "dessert_name": "Chocolate Cake",
                "quantity": 1,
                "customer_first_name": "jane",
                "customer_last_name": "doe",
                "customer_email": "jane.doe@gmail.com",
                "customer_phone_number": "555-555-5555",
                "customer_zip_code": "90210",
                "delivery_address": "123 Main St, Los Angeles, CA 90210",
                "scheduled_delivery_time": 1711108800,
                "order_total": 10.00,
                "order_status": "NEW",
                "order_date": 1711108800,
            }
        ],
    )

2 个回答

0

在这一行

@patch("src.routes.get_orders.admin_only", return_value=True)

你正在尝试从 src.routes.get_orders 调用这个函数

@patch("src.lib.authorization.admin_only", return_value=True)

这样做应该没问题。

1

因为 admin_only 是在一个依赖关系中使用的,所以在启动模块的时候会传递这个引用,这意味着如果你尝试修改它是没有效果的。解决这个问题的方法是使用 FastAPI 的 依赖覆盖。可以像这样做:

@freeze_time("2024-03-22 12:00:00")
def test_handler_valid_event_get_orders(orders_dynamodb_stub):
    app.dependency_overrides[admin_only] = lambda *args, **kargs: True)
    # Run your test
    app.dependency_overrides = {}

撰写回答