def test_get_todos():
# order = ASC
response = client.get("/todos")
assert response.status_code == 200
assert response.json() == {
"todos": [
{"id": 1, "contents": "FastAPI Section 0", "is_done":True},
{"id": 2, "contents": "FastAPI Section 1", "is_done": True},
{"id": 3, "contents": "FastAPI Section 2", "is_done": False},
]
}
# order = DESC
response = client.get("/todos?order=DESC")
assert response.status_code == 200
assert response.json() == {
"todos": [
{"id": 3, "contents": "FastAPI Section 2", "is_done": False},
{"id": 2, "contents": "FastAPI Section 1", "is_done": True},
{"id": 1, "contents": "FastAPI Section 0", "is_done": True},
]
}
- 이렇게 테스트 코드를 작성을 하다보면 함수가 두개가 있어 데이터 조회를 두번하게 된다.
- 테스트 코드를 작성하다보면 이런 식으로 API를 여러 번 호출하게 되는데 이럴 때마다 실제 데이터베이스에 데이터 요청이 가게 된다.
- 지금 같은 경우는 데이터를 조회하는 요청이기 때문에 크게 문제가 없을 수 있지만 데이터를 생성하거나 업데이트하거나 삭제하는 데이터를 변경하는 경우에는 실제 데이터베이스에 영향을 주게 된다.
- 이때 사용되는 기술이 mocking이라는 기술이다.
- 실제 데이터베이스에 요청을 하지 않지만 마치 데이터 베이스 요청을 한 것처럼 속이는, 흉내 내는 그런 기술
- 그렇다고 꼭 반드시 사용해야 되는 기술은 아니다.
- 예를 들어, 외부 API를 이용한다거나 데이터베이스 요청을 한다거나 하는 오래 걸리는 어떤 동작이 있을 때 그 부분을 mocking을 사용해서 대체를 하게 되면 실제로 그 부분이 동작을 하지 않아서 테스트 코드가 훨씬 빨리 동작하게 된다.
- 만약에 mocking을 사용하지 않고 매번 테스트마다 실제로 데이터베이스를 조회하게 됐을 때 데이터가 많다면 이 테스트 코드가 5~10분 1시간까지도 동작할수가 있다.
- 테스트 코드의 목적이 그런식으로 실제 데이터를 검증하는 것은 아니기 때문에 mocking이라는 기술을 사용하게 된다.
라이브러리 install
pip install pytest-mock
# main.py
@app.get("/todos", status_code=200)
def get_todos_handler(
order: str | None = None,
session: Session = Depends(get_db),
# 타입 힌트
) -> ToDoListSchema:
# 타입 힌트
todos: List[ToDo] = get_todos(session=session)
if order and order == "DESC":
return ToDoListSchema(
# todos: List[ToDoSchema] response.py에 이렇게 리스트 형식으로 작성해놨기 때문에 동일하게 []로 작성
todos=[ToDoSchema.model_validate(todo) for todo in todos[::-1]]
)
return ToDoListSchema(
todos=[ToDoSchema.model_validate(todo) for todo in todos]
)
# test_main.py
def test_get_todos(mocker):
# order = ASC
# mocker를 쓰며 실제로 이 함수를 동작시키는 것이 아니라 이 함수가 동작한 것처럼 속이겠다 라는 의미
# 그래서 DB에 들리지 않고 그냥 밑의 return_value 값으로 반환이 돼어 테스트하게 된다.
mocker.patch("main.get_todos", return_value=[
ToDo(id=1, contents="FastAPI Section 0", is_done=True),
ToDo(id=2, contents="FastAPI Section 1", is_done=False),
])
response = client.get("/todos")
assert response.status_code == 200
assert response.json() == {
"todos": [
{"id": 1, "contents": "FastAPI Section 0", "is_done":True},
{"id": 2, "contents": "FastAPI Section 1", "is_done": False},
]
}
# order = DESC
response = client.get("/todos?order=DESC")
assert response.status_code == 200
assert response.json() == {
"todos": [
{"id": 2, "contents": "FastAPI Section 1", "is_done": False},
{"id": 1, "contents": "FastAPI Section 0", "is_done": True},
]
}
- mocker를 쓸 함수 파라미터에 인자를 주입시켜 mocker를 작성해준다.
- mocking은 실제 코드가 동작하기 전에 적용을 해줘야 한다.
- 그래서 mocking을 하는게 뭐냐면 특정 함수를 가로채서 원하는 값을 대신 반환하게 만드는 것이다.(return_value 값으로 반환을 해준다.)
- DB, 외부 API 등 내 코드가 아닌 것들을 가짜로 대체해서 내 로직만 순수하게 테스트할 수 있게 만들어주는 것
- main에 있는 get_todos를 모킹할거다. 라고 작성해준것
(todos) PS C:\Users\user\Desktop\hyun\fastpai\todos\src> pytest
=============================================================== test session starts ===============================================================
platform win32 -- Python 3.14.6, pytest-9.1.1, pluggy-1.6.0
rootdir: C:\Users\user\Desktop\hyun\fastpai\todos\src
plugins: anyio-4.13.0, mock-3.15.1
collected 2 items
tests\test_main.py .. [100%]
================================================================ warnings summary =================================================================
..\Lib\site-packages\fastapi\testclient.py:1
C:\Users\user\Desktop\hyun\fastpai\todos\Lib\site-packages\fastapi\testclient.py:1: StarletteDeprecationWarning: Using `httpx` with `starlette.testclient` is deprecated; install `httpx2` instead.
from starlette.testclient import TestClient as TestClient # noqa
schema\response.py:6
C:\Users\user\Desktop\hyun\fastpai\todos\src\schema\response.py:6: PydanticDeprecatedSince20: Support for class-based `config` is deprecated, use ConfigDict instead. Deprecated in Pydantic V2.0 to be removed in V3.0. See Pydantic V2 Migration Guide at https://errors.pydantic.dev/2.13/migration/
class ToDoSchema(BaseModel):
-- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html
========================================================== 2 passed, 2 warnings in 0.77s =========================================================
그럼 이와 같이 테스트가 잘 된다.
'FastAPI > 테스트 코드' 카테고리의 다른 글
| GET 단일 조회 API (0) | 2026.07.07 |
|---|---|
| PyTest Fixture (0) | 2026.07.07 |
| GET 전체 조회 API (0) | 2026.07.06 |
| PyTest란? (0) | 2026.07.01 |
| 테스트 코드란? (0) | 2026.07.01 |