목차
개요
이번 글의 주제는 지난번 글에서 기재한 내용 중 일부를 이용해 FastAPI에서 테스트 코드 작성 시에 dependency-injector를 통해 이를 조정할 수 있게 만드는 방법을 기록한다.
1. app.py를 사용 시 외부환경 고려하기
지난 글에서 사용한 app.py는 다음과 같이 생긴 코드이다.
# app.py
from fastapi import FastAPI
from src.config import setup
class FastApi:
def __init__(self, app):
self.app = app
def __call__(self, *args, **kwargs):
setup.router(self.app)
setup.container()
return self.app
server = FastApi(app=FastAPI())
그런데 이는 FastAPI가 시작될 때 지극히도 내부에 설정된 환경을 기반으로 동작한다는 것에 문제가 있다. 이에 대한 문제 사례 중 하나는 TestClient를 사용할 때이다.
2. FastAPI의 TestClient
FastAPI의 TestClient는 다음과 같은 형태로 사용할 수 있다.
from fastapi.testclient import TestClient
from src.adapters.repository import exceptions
from src.main import app
import pytest
from src.libraries.utils import token
client = TestClient(app)
def test_case01():
response = client.post(
'/api',
data={"key1": "va1"}
)
assert response.status_code == 200
TestClient라는 객체에 FastAPI 인스턴스를 넘겨줌으로써 사용할 수 있다. 손쉽게 사용할 수 있지만 앞에서 작성해 놓은 app.py를 그대로 이용하게 될 경우 Test 환경으로 전환을 하지 못한다
3. dependency-injector를 이용하여 관리하기
DataBase 연결에 대한 정보를 관리하기 위해서 class를 추상화하여 사용하는 방법도 있지만 필자는 dependency-injector를 사용 중이었기에 dependency-injector에서 외부로터 데이터를 받아 사용할 수 있는 방법이 필요했다. 필자가 찾은 방법은 config provider를 이용하는 것이었다.
3.1 dependency-injector의 Configuration 프로바이더
dependency-injector는 의 Configuration 프로바이더는 다음과 같이 사용한다.
from __future__ import annotations
from dependency_injector import containers, providers
class DataBaseConfig(containers.DeclarativeContainer):
config = providers.Configuration()
Container안에 providers.Configuation()을 정의한다. 이렇게 정의를 하고 나면 아래와 같은 방식으로 외부에서 값을 설정할 수 있게 된다.
# Container Instance를 선언하고 값 설정
database_config = database.DataBaseConfig()
session_container.config.from_dict({
'drivername': "DRIVER_NAME",
'username': "USERNAME",
'password': "PASSWORD",
'database': "DATABASE",
'host': "HOST",
'port': "PORT"
})
다시 DataBaseConfig Container 안에서 선언해 둔 config를 외부에서 설정한 속성을 이용할 수 있게 된다.
class DataBaseContainer(containers.DeclarativeContainer):
config = providers.Configuration()
session = providers.Singleton(
SqlAlchemySessionFactory.get_session,
drivername=config.drivername,
username=config.username,
password=config.password,
database=config.database,
host=config.host,
port=config.port
)
4. Test 환경으로 전환점 만들기
다시 돌아와서 app.py의 내용을 다음과 같이 고치도록 하자.
# app.py
from fastapi import FastAPI
from src.config import setup
DATABASE_CONFIG = {
"drivername" : "",
"host": "",
"port" : 1234,
"database" : "",
"username" : "",
"password" :""
}
class FastApi:
def __init__(self, app, database):
self.app = app
self.database = database
def __call__(self, *args, **kwargs):
setup.router(self.app)
setup.container(self.database)
return self.app
server = FastApi(app=FastAPI(), database=DATABASE_CONFIG)
위와 같이 선언하면 TestClient를 이용할 때 다음과 같이 사용할 수 있게 된다.
from fastapi.testclient import TestClient
from src.adapters.repository import exceptions
from src.main import app
import pytest
from src.libraries.utils import token
app = FastApi(app=FastAPI(), database=TEST_DATABASE)
client = TestClient(app)
def test_case01():
response = client.post(
'/api',
data={"key1": "va1"}
)
assert response.status_code == 200
'Frame Work > FastAPI' 카테고리의 다른 글
[FastAPI] Header Authenticate와 Swagger Authorize (1) | 2023.11.27 |
---|---|
[FastAPI] Post API의 Form Body 테스트 (0) | 2023.10.11 |
[FastAPI] DI는 bootstrapping을 생각해보기 (0) | 2023.10.06 |
[FastAPI] 실행은 Factory Pattern을 적용하자. (0) | 2023.09.15 |
[FastAPI] Pydantic GenericModel을 이용한 Response Data 문서화 (0) | 2023.08.15 |