Skip to content

[Q] Provider override not working with subcontainers #851

Open
@TojikCZ

Description

@TojikCZ

Sorry for the second post today, i am kinda at the end of my ropes here
I would be so happy if someone manages to get me unstuck.

I have three levels of containers. Root, Main and module specific
In component/unit tests when I want to override a provider, it only works if I instantiate the module specific container like UtilsContainer and orverride its database provider
If I instead make an instance of RootContainer and do
with container.main_package.utils_package.database.override(mocked_db):
it does not work and the original container is used

I placed a raise statement before my RootContainer init in the main code. Does not get triggered, so that instance does not get created from a spurious import somewhere

I am trying to do this without getting a reference to the root container, instead hoping that I can create a new instance in my test, override there and have that injected in whatever I call from the test

My service does not get the container reference, it injects like so: database: PostgresDatabase = Provide[UtilsContainer.database]

conftest.py

from unittest.mock import AsyncMock

import pytest

from somewhere.adapters.dependency_injection.root_container import (
    RootContainer,
)
from somewhere.adapters.postgres import PostgresDatabase
from somewhere.utilities.schemas import Health


@pytest.fixture
def container(request):
    """Creates container"""
    container = RootContainer()
    container.init_resources()

    overrides = request.param
    generators = []
    for override_fn in overrides:
        generators.append(override_fn(container))

    for generator in generators:
        next(generator)

    yield container

    for generator in generators:
        try:
            next(generator)
        except StopIteration:
            pass

    container.unwire()


def unhealthy_database(container):
    mocked_db = AsyncMock(spec=PostgresDatabase)
    mocked_db.health.return_value = Health.FAILING
    with container.main_package.utils_package.database.override(mocked_db):
        yield

test_utilities.py

import pytest

from somewhere.utilities.schemas import Health
from somewhere.utilities.service import get_health_status
from tests.component.conftest import unhealthy_database, healthy_database


@pytest.mark.asyncio
@pytest.mark.parametrize("container", [[unhealthy_database]], indirect=True)
async def test_unhealthy(container):
    health_status = await get_health_status()
    assert health_status.app == Health.OK
    assert health_status.db == Health.FAILING

I am open to distilling this into a minimal example, but I fear I am missing something simple.
Thank you

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions