Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Using container as a parameter for FastAPI integration testing #695

Unanswered
rtnolan asked this question in Q&A
Discussion options

Hi there,

Firstly just wanted to say thanks for taking the time to share an example of how to hook this up using FastAPI, it's been extremely useful and a great starting point.

I wanted to take the testing aspect one step further and run some full end-to-end tests that actually persist to a database (sqlite) to also check that everything was working as expected (even the repositories). I modified the app creation to more or less resemble this:

# container.py
class Container(containers.DeclarativeContainer):
 wiring_config = containers.WiringConfiguration(
 modules=["app.routers.routerA"]
 )
 
 config = providers.Configuration(yaml_files=["config.yml"])
 
 db = providers.Singleton(Database, db_url=config.db.url)
 A_repo = providers.Factory(
 RepoA, session_factory=db.provided.session
 )
 
# server.py
def create_server(container):
 app = FastAPI()
 
 app.container = container
 app.include_router(routerA)
 return app

I've then modified my tests to look like:

from app.server import create_server
class TestContainer(containers.DeclarativeContainer):
 wiring_config = containers.WiringConfiguration(
 modules=["app.routers.routerA"]
 )
 
 config = providers.Configuration(yaml_files=["test.config.yml"])
 
 db = providers.Singleton(Database, db_url=config.db.url)
 A_repo = providers.Factory(
 RepoA, session_factory=db.provided.session
 )
 
container = TestContainer()
app = create_server(container)
@pytest.fixture
def client():
 yield TestClient(app)

My issue now is that in one of my tests where I'm testing to see if an exception is raised correctly, instead of catching the side-effect and being able to assert it's how I expect it's breaking because of the exception being raised. It looks like such:

async def test_get_by_id_err(client):
 repository_mock = mock.Mock(spec=RepoA)
 repository_mock.get_by_id.side_effect = ResourceNotFound(
 "Resource could not be found. Please provide a valid ID.",
 )
 with app.container.A_repo.override(repository_mock):
 request = client.get("/resource/notexistent")
 response = request.json()
 assert request.status_code == 404

This just results in a stacktrace for the above side_effect being thrown in the route. However when not making the container a parameter to the app creation i.e.

def create_server():
 app = FastAPI()
 container = Container()
 app.container = container
 app.include_router(routerA)
 return app

this test works absolutely fine. Which leads me to believe it's got something to do how the mock is behaving with the Container. I'm relatively new to testing with DI and Python so I might just be doing silly here but I can't understand why one would work and the other wouldn't. Would you have any insight into why this might be happening? (Hope everything there is clear in what I mean, happy to create a small sample repo if it doesn't make sense) Any help would very much be appreciated!

You must be logged in to vote

Replies: 0 comments

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Category
Q&A
Labels
None yet
1 participant

AltStyle によって変換されたページ (->オリジナル) /