为什么路由测试失败?



我一直跟着测试驱动。使用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,portpath。然而,如下所示,我的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中设置testing1,在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试图将你的字典作为函数调用,这暗示了它期望一个函数来代替。