Provider overriding

You can override any provider with another provider.

When provider is overridden it calls to the overriding provider instead of providing the object by its own.

This helps in testing. This also helps in overriding API clients with stubs for the development or staging environment.

To override a provider you need to call the Provider.override() method. This method receives a single argument called overriding. If the overriding value is a provider, this provider is called instead of the original. If value is not a provider, this value is returned instead of calling the original provider.

../_images/overriding.png
importdataclasses
importunittest.mock
fromdependency_injectorimport containers, providers
classApiClient:
 ...
classApiClientStub(ApiClient):
 ...
@dataclasses.dataclass
classService:
 api_client: ApiClient
classContainer(containers.DeclarativeContainer):
 api_client_factory = providers.Factory(ApiClient)
 service_factory = providers.Factory(
 Service,
 api_client=api_client_factory,
 )
if __name__ == "__main__":
 container = Container()
 # 1. Use .override() to replace the API client with stub
 container.api_client_factory.override(providers.Factory(ApiClientStub))
 service1 = container.service_factory()
 assert isinstance(service1.api_client, ApiClientStub)
 # 2. Use .override() as a context manager to mock the API client in testing
 with container.api_client_factory.override(unittest.mock.Mock(ApiClient)):
 service2 = container.service_factory()
 assert isinstance(service2.api_client, unittest.mock.Mock)
 # 3. Use .reset_override() to get back to normal
 container.api_client_factory.reset_override()
 service3 = container.service_factory()
 assert isinstance(service3.api_client, ApiClient)

You can override a provider multiple times. In that case the latest overriding value will be used. The rest of the overriding values will form a stack.

To reset an overriding you can use the Provider.reset_override() or Provider.reset_last_overriding() methods.

You can use a context manager for overriding a provider with Provider.override():. The overriding will be reset when context closed.