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를 사용할 수 있게 된다.