Pytest integration for Modern-DI — turn any DI dependency into a pytest fixture with one line.
Full guide: pytest integration docs
Installation
uv add --dev modern-di-pytest # or: pip install modern-di-pytest
Usage
The user owns the root container fixture. Pick whatever pytest scope fits the test suite:
# conftest.py
import typing
import modern_di
import pytest
from modern_di_pytest import expose, modern_di_fixture
from app import ioc
from app.ioc import Dependencies
from app.services import EmailClient
@pytest.fixture
def di_container() -> typing.Iterator[modern_di.Container]:
with modern_di.Container(groups=ioc.ALL_GROUPS) as container:
container.validate() # 3.1: graph validation is an explicit call now
yield container
# Bulk: every Provider on each group becomes a pytest fixture
# named after the class attribute. Pass several groups in one call.
expose(Dependencies)
# Manual: turn a single type or Provider into a named fixture.
email_client = modern_di_fixture(EmailClient)
Tests then receive resolved dependencies by name:
from app.services import EmailClient, UserService
def test_listing(user_service: UserService) -> None: # generated by expose(Dependencies)
assert user_service.list_users() == []
def test_email(email_client: EmailClient) -> None: # generated manually
email_client.send("hi")
Pointing a fixture at a child container
import typing
import modern_di
import pytest
from modern_di_pytest import modern_di_fixture
from app.services import UserService
@pytest.fixture
def request_container(
di_container: modern_di.Container,
) -> typing.Iterator[modern_di.Container]:
with di_container.build_child_container(scope=modern_di.Scope.REQUEST) as container:
yield container
request_user_service = modern_di_fixture(UserService, container_fixture="request_container")
Overrides
Use Container.override() directly — modern-di already ships a first-class
override mechanism backed by a tree-shared OverridesRegistry:
import modern_di
from app.ioc import Dependencies
from app.services import UserService
from tests.fakes import FakeRepo
def test_with_override(
di_container: modern_di.Container,
user_service: UserService,
) -> None:
di_container.override(Dependencies.user_repo, FakeRepo())
try:
assert user_service.list_users() == []
finally:
di_container.reset_override(Dependencies.user_repo)
API
modern_di_fixture(dependency, *, container_fixture="di_container", name=None, pytest_scope="function")
Turn a single dependency into a pytest fixture. dependency is either a
type or a Provider; the generated fixture resolves it through
container.resolve_dependency. The returned object is a real pytest fixture
— assign it to a module-level name and pytest will collect it.
expose(*groups, container_fixture="di_container", pytest_scope="function", module=None)
Walk each Group subclass in groups and install one pytest fixture per
Provider class attribute onto the caller's module. Fixture names equal the
class-attribute names. Non-Provider class attributes are skipped. A duplicate
attribute name across groups raises ValueError, and calling it with no
groups raises TypeError. Pass module= explicitly when stack
introspection cannot identify the caller.
📦 PyPI
📝 License
Part of modern-python
Built on modern-di, a dependency-injection framework with IoC container and scopes.
Browse the full list of templates and libraries in
modern-python — see the org profile for the categorized index.
Metadata
Release files for modern-di-pytest 3.0.3
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| modern_di_pytest-3.0.3.tar.gz | 5.2 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| modern_di_pytest-3.0.3-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 10.8 kB
Release files / modern_di_pytest-3.0.3.tar.gz
| Download URL | modern_di_pytest-3.0.3.tar.gz |
|---|---|
| Size | 5.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
2dcb61f12359ca6fc6c21cf629b218cf25ce2729f34f16d5039f23cee7d62fe2
|
|
BLAKE2b-256 checksum How to use checksums |
10574039eba3c7e8ca8c2e958e2fcd4e1e184c86083aba1262e28744cd98224b
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.12.17 {"installer":{"name":"uv","version":"0.12.17","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / modern_di_pytest-3.0.3-py3-none-any.whl
| Download URL | modern_di_pytest-3.0.3-py3-none-any.whl |
|---|---|
| Size | 5.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
153dad355106f404d8b0539a60939af583cd2837527e19c494c36197c3344c94
|
|
BLAKE2b-256 checksum How to use checksums |
a0f624a37a2e0339b90e011901e8b9cae28e0718aec6830dab14f523d280c330
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.12.17 {"installer":{"name":"uv","version":"0.12.17","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|