I have a project that uses FastApi and Pydantic-settings. While the injection of settings works fine i am not able to override them in test.
My settings look like this:
class LevelDBSettings(BaseSettings):
"""
Settings for the levelDB database.
"""
fetch_url: str
"""URL to fetch data from levelDB"""
read_token: str
"""Token to authenticate against levelDB"""
model_config = SettingsConfigDict(env_file="dev_default.env", env_file_encoding="utf-8")
def __init__(self):
super().__init__(self.model_config)
def get_level_db_settings():
"""provide level db settings application wide. injectable via dependency injection"""
return LevelDBSettings()
Injecting them also works fine:
def get_data_from_db(msn: str, start: datetime, end: datetime):
request = FetchRequest(start, end, msn)
settings = Annotated[LevelDBSettings, Depends(get_level_db_settings)]()
# inject settings
As you see i put the method to get setings in settings class for 2 reasons:
- it just belongs here (my opinion)
- if put in file with app = FastAPI() i get circular dependency errors. because app imports routers that call methods that inject settings from fast api - circle
First question: is this a general problem? Can i only use "dependency_overrides" for methods in app? (How to inject arbitrary things and override them in tests?)
My test is this (separate path /tests/integration)
def get_test_level_db_settings():
settings = LevelDBSettings()
settings.fetch_url = "http://localhost:8080/api/v0/fetch"
settings.read_token = "sometest"
return settings
def test_fetch_data():
app.dependency_overrides[get_level_db_settings] = get_test_level_db_settings
...
This test fails due to missing settings in pydantic-settings (it can not load env file because test runs in different folder)
How to get this working?
app.dependency_overridesworks only for replacing injected dependencies, i.e.DependsorAnnotatedparameters of your routes.If your function/callable is not injected, you should use a different technique to "patch" it. I personally use
patchfromunittest.mockwhen I cannot useapp.dependency_overrides.Note that you didn't provide an explicit example on how your settings are used in your routes. Maybe we can help you refactor your example to inject the settings as a dependency.