Тестування залежностей з переписуваннями¶
🌐 Переклад ШІ та людьми
Цей переклад виконано ШІ під керівництвом людей. 🤝
Можливі помилки через неправильне розуміння початкового змісту або неприродні формулювання тощо. 🤖
Ви можете покращити цей переклад, допомігши нам краще спрямовувати AI LLM.
Переписування залежностей під час тестування¶
Є сценарії, коли ви можете захотіти переписати залежність під час тестування.
Ви не хочете запускати оригінальну залежність (ані будь-які її підзалежності).
Натомість ви хочете надати іншу залежність, яку буде використано лише під час тестів (можливо, тільки в окремих тестах), і яка повертатиме значення, що підставляється всюди, де раніше використовувалося значення оригінальної залежності.
Випадки використання: зовнішній сервіс¶
Наприклад, у вас є зовнішній постачальник автентифікації, який потрібно викликати.
Ви надсилаєте йому токен, і він повертає автентифікованого користувача.
Такий постачальник може стягувати плату за кожний запит, а виклик може займати більше часу, ніж використання фіксованого фальшивого користувача для тестів.
Ймовірно, ви хочете протестувати зовнішнього постачальника один раз, але не обов'язково викликати його для кожного тесту.
У такому разі ви можете переписати залежність, що викликає цього постачальника, і використати власну залежність, яка повертає фальшивого користувача, лише для ваших тестів.
Використовуйте атрибут app.dependency_overrides¶
Для таких випадків ваш застосунок FastAPI має атрибут app.dependency_overrides, це простий dict.
Щоб переписати залежність для тестування, вкажіть у ключі оригінальну залежність (функцію), а значенням - ваше переписування залежності (іншу функцію).
Після цього FastAPI викликатиме це переписування замість оригінальної залежності.
from typing import Annotated
from fastapi import Depends, FastAPI
from fastapi.testclient import TestClient
app = FastAPI()
async def common_parameters(q: str | None = None, skip: int = 0, limit: int = 100):
return {"q": q, "skip": skip, "limit": limit}
@app.get("/items/")
async def read_items(commons: Annotated[dict, Depends(common_parameters)]):
return {"message": "Hello Items!", "params": commons}
@app.get("/users/")
async def read_users(commons: Annotated[dict, Depends(common_parameters)]):
return {"message": "Hello Users!", "params": commons}
client = TestClient(app)
async def override_dependency(q: str | None = None):
return {"q": q, "skip": 5, "limit": 10}
app.dependency_overrides[common_parameters] = override_dependency
def test_override_in_items():
response = client.get("/items/")
assert response.status_code == 200
assert response.json() == {
"message": "Hello Items!",
"params": {"q": None, "skip": 5, "limit": 10},
}
def test_override_in_items_with_q():
response = client.get("/items/?q=foo")
assert response.status_code == 200
assert response.json() == {
"message": "Hello Items!",
"params": {"q": "foo", "skip": 5, "limit": 10},
}
def test_override_in_items_with_params():
response = client.get("/items/?q=foo&skip=100&limit=200")
assert response.status_code == 200
assert response.json() == {
"message": "Hello Items!",
"params": {"q": "foo", "skip": 5, "limit": 10},
}
🤓 Other versions and variants
Tip
Prefer to use the Annotated version if possible.
from fastapi import Depends, FastAPI
from fastapi.testclient import TestClient
app = FastAPI()
async def common_parameters(q: str | None = None, skip: int = 0, limit: int = 100):
return {"q": q, "skip": skip, "limit": limit}
@app.get("/items/")
async def read_items(commons: dict = Depends(common_parameters)):
return {"message": "Hello Items!", "params": commons}
@app.get("/users/")
async def read_users(commons: dict = Depends(common_parameters)):
return {"message": "Hello Users!", "params": commons}
client = TestClient(app)
async def override_dependency(q: str | None = None):
return {"q": q, "skip": 5, "limit": 10}
app.dependency_overrides[common_parameters] = override_dependency
def test_override_in_items():
response = client.get("/items/")
assert response.status_code == 200
assert response.json() == {
"message": "Hello Items!",
"params": {"q": None, "skip": 5, "limit": 10},
}
def test_override_in_items_with_q():
response = client.get("/items/?q=foo")
assert response.status_code == 200
assert response.json() == {
"message": "Hello Items!",
"params": {"q": "foo", "skip": 5, "limit": 10},
}
def test_override_in_items_with_params():
response = client.get("/items/?q=foo&skip=100&limit=200")
assert response.status_code == 200
assert response.json() == {
"message": "Hello Items!",
"params": {"q": "foo", "skip": 5, "limit": 10},
}
Порада
Ви можете налаштувати переписування для залежності, яка використовується де завгодно у вашому застосунку FastAPI.
Оригінальна залежність може використовуватися у функції операції шляху, у декораторі операції шляху (коли ви не використовуєте повернуте значення), у виклику .include_router() тощо.
FastAPI усе одно зможе її переписати.
Потім ви можете скинути переписування (видалити їх), встановивши для app.dependency_overrides порожній dict:
app.dependency_overrides = {}
Порада
Якщо ви хочете переписувати залежність лише під час окремих тестів, встановіть переписування на початку тесту (всередині тестової функції) і скиньте його наприкінці (в кінці тестової функції).