FastAPI/테스트 코드

PyTest Fixture

hyunai 2026. 7. 7. 15:51
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를 사용하고 있다.
  • 근데 생각해보면 이 mocker를 따로 import를 하거나 하지 않았지만 pytest-mock이라는 라이브러리를 install 했을 때 그 라이브러리 안에 이런 mocker라는 fixture가 이미 정의가 되어 있기 때문에 테스트 코드에서 mocker를 바로 가져와서 사용할 수 있는 것.
# test_main.py
# testclient import
from database.orm import ToDo
from fastapi.testclient import TestClient

# main.py에서 app import
from main import app

# 이 client 객체를 이용해서 여기에 어떤 API 요청을 보내보는 형태
client = TestClient(app=app)
  • 지금 작성된 TestClient는 다른 테스트 파일이 추가된다고 할 때 그 파일들에서도 사용할 수 있다.
  • 이런 식으로 어떤 파일마다 이 객체를 생성하는게 아니라 미리 fixture로 등록을 해두게 되면 재사용 할 수 있다.
# conftest.py

import pytest

from fastapi.testclient import TestClient
from main import app

@pytest.fixture()
def client():
    return TestClient(app=app)
  • tests의 python package 밑에 conftest라는 python 파일을 만든다.
  • 함수 형태로 fixture를 만들어야한다.
  • return으로 새로 생성된 TestClient 객체를 넘겨주도록 한다.
  • client를 fixture로 사용하기 위해 pytest에 fixture라는 데코레이터를 추가해줘야된다.
    • 그럼 pytest가 이 client란 함수를 fixture로 인식을 해서 테스트 코드 안에서 글로벌하게 사용할 수 있게 된다.
# test_main.py

# testclient import
from database.orm import ToDo

def test_health_check(client):
    # get 요청의 응답을 response라는 변수로 할당
    response = client.get("/")
    assert response.status_code == 200
    assert response.json() == {"ping" : "pong"}

def test_get_todos(client, mocker):
    # order = ASC

    # mocker를 쓰며 실제로 이 함수를 동작시키는 것이 아니라 이 함수가 동작한 것처럼 속이겠다 라는 의미
    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},
        ]
    }
  • 기존에 있던 import 문들은 다 정리가 가능해진다.
  • 함수의 인자로 client를 사용해서 pytest에 fixture를 사용할 수 있게 된다.

'FastAPI > 테스트 코드' 카테고리의 다른 글

POST API  (0) 2026.07.10
GET 단일 조회 API  (0) 2026.07.07
PyTest Mocking  (0) 2026.07.07
GET 전체 조회 API  (0) 2026.07.06
PyTest란?  (0) 2026.07.01