I have been playing with https://docs.litestar.dev/2/tutorials/todo-app/3-assembling-the-app.html#final-application and wanted to create some tests for it.
Namely, I wanted a test that after I create a TodoItem
I am able to get it by name.
To do that, I have created a test client using create_test_client
and provided route_handlers
from the app
. Also, I have changed the "todo_list"
dependency so it uses a local function that provides a test global ITEMS = []
(I had been also trying with fixture local itesms = []
with the same results).
At some point during injecting dependecies global ITEMS
gets copied (the id()
of the object changes) and my route handle get_item
get different todo_list
then add_item
, so the item that has been appened in add_item
is not visible in get_item
.
No response
`app.py`
from dataclasses import dataclass
from typing import Annotated
import msgspec
from litestar import Litestar, get, post
from litestar.di import Provide
from litestar.exceptions import NotFoundException
from litestar.params import Dependency
@dataclass
class TodoItem:
title: str
done: bool
deadline: Annotated[int, msgspec.Meta(ge=1)] | None = None
def __post_init__(self):
if self.done and self.deadline is not None:
raise ValueError("Done tasks cannot have a deadline")
TODO_LIST: list[TodoItem] = [
TodoItem(title="Start writing TODO list", done=True),
TodoItem(title="???", done=False),
TodoItem(title="Profit", done=False),
]
def get_todo_list():
return TODO_LIST
@post("/")
async def add_item(todo_list: Annotated[list[TodoItem], Dependency], data: TodoItem) -> list[TodoItem]:
todo_list.append(data)
return todo_list
def get_todo_by_title(todo_name, todo_list) -> TodoItem:
for item in todo_list:
if item.title == todo_name:
return item
raise NotFoundException(detail=f"TODO {todo_name!r} not found")
@get("/{item_title:str}")
async def get_item(todo_list: Annotated[list[TodoItem], Dependency], item_title: str) -> TodoItem:
return get_todo_by_title(item_title, todo_list)
app = Litestar([get_item, add_item], dependencies={"todo_list": Provide(get_todo_list)})
`test_app.py`
```py
import pytest
from litestar.di import Provide
from litestar.testing import create_test_client
import app
ITEMS =[]
@pytest.fixture
def test_client():
items = []
def get_todo_list_mock():
return ITEMS
# the above seems to not work - no idea why
try:
# with TestClient(app=app.app) as client:
with create_test_client(route_handlers=[app.get_list, app.get_item, app.add_item, app.update_item],
dependencies={"todo_list": Provide(get_todo_list_mock)}) as client:
yield client
finally:
ITEMS.clear()
def test_create_and_get_item(test_client):
task_name = 'new'
item = {'title': task_name, 'done': False, 'deadline': 4}
r = test_client.post("/", json=item)
assert r.status_code == 201
r2 = test_client.get(f"/{task_name}")
assert r2.status_code == 200
assert r2.json() == item
### Steps to reproduce
```bash
just use the code snippets provided
No response
No response
2.2.1
Pay now to fund the work behind this issue.
Get updates on progress being made.
Maintainer is rewarded once the issue is completed.
You're funding impactful open source efforts
You want to contribute to this effort
You want to get funding like this too