Enhancement: Override dependecies for testing #1154
Replies: 9 comments
-
@abdulhaq-e thanks for wanting to contribute! The def test_health_check():
with create_test_client(route_handlers=[health_check], dependencies={"foo": Provide(bar)}) as client:
response = client.get("/health-check")
assert response.status_code == HTTP_200_OK
assert response.text == "healthy" Whats not possible to do with this pattern is to override the dependencies defined on lower levels, or for that matter - any of the other key / value pairs that are defined on the different layers. I can see the use case for such overrides, so I think its a feature we should consider adding. The question is how to implement it. |
Beta Was this translation helpful? Give feedback.
-
@abdulhaq-e - I am closing this issue due to lack of activity. You're welcome to reopen it if you wish to contribute. |
Beta Was this translation helpful? Give feedback.
-
For anyone else who's found their way here: if you're trying to override your database dependencies for testing and you're using the SQLAlchemy plugin, what you should actually do is set |
Beta Was this translation helpful? Give feedback.
-
Do you want to share a code snippet? |
Beta Was this translation helpful? Give feedback.
-
We have this section in our documentation regarding dependency overrides for testing purposes: While FastAPI includes a mechanism to override dependencies on an existing application object, Starlite promotes architecular solutions to the issue this is aimed to solve. Therefore, overriding dependencies in Starlite is strictly supported at definition time, i.e. when you’re defining handlers, controllers, routers and applications. Dependency overrides are fundamentally the same idea as mocking and should be approached with the same caution and used sparingly instead of being the default. In this particular example, this would mean that instead of setting |
Beta Was this translation helpful? Give feedback.
-
Thanks for the advice @provinzkraut, but I'm using a pytest fixture (from pytest_mock_resources) to manage temporary database instances and another to roll back changes between tests, and I don't feel like figuring out if everything still works when all I pass in is the connection string. As for that section from the FastAPI page in the docs:
I'm using an application factory in my main module, so I can create a test application which is the same as the real one in every way except for the database config: def create_app(engine=None, session_maker=None) -> Starlite:
# Patch out real DB for testing
if engine:
sqlalchemy_config.engine_instance = engine
if session_maker:
sqlalchemy_config.session_maker_instance = session_maker
sqlalchemy_plugin = SQLAlchemyPlugin(config=sqlalchemy_config)
return Starlite(
plugins=[sqlalchemy_plugin],
# The rest of my application setup
...
)
# Normally: uvicorn --factory app.main:create_app
# From tests: app = create_app(engine=engine, session_maker=lambda: session)
# where engine and session are pytest fixtures |
Beta Was this translation helpful? Give feedback.
-
The connection string thing was actually just meant as an example, I'm sorry if hadn't made that clear. The solution you showed is actually another good example of the pattern I suggested in 1), although I'd set it up slightly different: Instead of patching the attributes, I'd create the def create_app(engine=None, session_maker=None) -> Starlite:
sqlalchemy_config = SQLAlchemyConfig(
... # other configuration
engine_instance=engine,
session_maker_instance=session_maker,
)
sqlalchemy_plugin = SQLAlchemyPlugin(config=sqlalchemy_config)
return Starlite(
plugins=[sqlalchemy_plugin],
... # The rest of my application setup
) |
Beta Was this translation helpful? Give feedback.
-
Okay I thought this was a better idea too, but actually there's a validator on |
Beta Was this translation helpful? Give feedback.
-
@mje-nz I think you misunderstood my suggestion. I'm not saying you should pass |
Beta Was this translation helpful? Give feedback.
-
What's the feature you'd like to ask for.
It would be nice to have a way to override dependencies for testing purposes. I'm thinking of an API such as:
or with the helper function
This would override regardless of the layer at which the dependency is injected at. I'm thinking it would be a step after
resolving_all_dependencies
Additional context
I'm not sure how feasible both of these are, I spent sometime reviewing the codebase on the weekend and then I ended up using
monkeypatching
to override the dependencies.What do you think?
Beta Was this translation helpful? Give feedback.
All reactions