我一直跟着测试驱动。使用Docker设置FastAPI的教程。我使用PyTest编写的第一个测试出现以下错误消息:
TypeError: Settings(environment='dev', testing=True, database_url=AnyUrl('postgres://postgres:postgres@web-db:5432/web_test', scheme='postgres', user='*****', password='*****', host='web-db',host_type='int_domain', port='5432', path='/web_test')) is not a callable object.
看图片,你会注意到Settings对象有一个奇怪的形式;特别是,它的database_url
参数似乎包裹了一堆其他参数,如password
,port
和path
。然而,如下所示,我的Settings类采用了不同的形式。
Fromconfig.py
:
# ...imports
class Settings(BaseSettings):
environment: str = os.getenv("ENVIRONMENT", "dev")
testing: bool = os.getenv("TESTING", 0)
database_url: AnyUrl = os.environ.get("DATABASE_URL")
@lru_cache()
def get_settings() -> BaseSettings:
log.info("Loading config settings from the environment...")
return Settings()
然后,在conftest.py
模块中,我用以下内容覆盖了上面的设置:
import os
import pytest
from fastapi.testclient import TestClient
from app.main import create_application
from app.config import get_settings, Settings
def get_settings_override():
return Settings(testing=1, database_url=os.environ.get("DATABASE_TEST_URL"))
@pytest.fixture(scope="module")
def test_app():
app = create_application()
app.dependency_overrides[get_settings] = get_settings_override()
with TestClient(app) as test_client:
yield test_client
对于有问题的测试本身,它看起来像这样:
def test_ping(test_app):
response = test_app.get("/ping")
assert response.status_code == 200
assert response.json() == {"environment": "dev", "ping": "pong", "testing": True}
容器在我的本地主机上成功运行,没有问题;这使我相信这个问题完全与我如何设置测试及其相关配置有关。但是,错误的结构以及database_url如何包装来自docker-compose的所有这些键值对。Yml让我感觉我的语法错误可能在其他地方。
在这个关键时刻,我不确定这个问题是否与我如何设置test_ping.py
,我的settings_override的构造,我的docker-compose.yml
文件的格式或其他东西有关。
到目前为止,我试图通过阅读在FastApi中使用依赖覆盖来解决这个问题,在dockers -compose中处理我的缩进,将TestClient
从starlette提供的更改为FastApi提供的,并手动进入测试模式。
当我尝试手动进入测试模式时,我注意到容器不想跟随。我试过在docker-compose.yml
中设置testing
为1
,在config.Settings
中设置testing: bool = True
。
我对这里的所有相关技术都很陌生,很困惑。是什么导致我的测试结果不一致?任何和所有的见解将非常感激。如果您需要查看任何其他文件,或者对包结构感兴趣,请告诉我。多谢。
任何通过app.dependency_overrides
覆盖的依赖项都应该提供被覆盖的函数作为键,而应该使用函数。在您的情况下,您正在分配正确的重写,但是您将函数的结果分配为重写,而不是重写本身:
app.dependency_overrides[get_settings] = get_settings_override()
. .这应该是:
app.dependency_overrides[get_settings] = get_settings_override
错误信息显示FastAPI试图将你的字典作为函数调用,这暗示了它期望一个函数来代替。