question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Overrides aren't resetted if container is created in pytest.fixture with scope session or module

See original GitHub issue

I have a simple example application:

# my_app.py

import sys
from dependency_injector import containers, providers
from dependency_injector.wiring import inject, Provide


class MyResource:
    def __init__(self, value):
        self.value = value

    def provide(self):
        return self.value


class MyService:
    def __init__(self, resource: MyResource):
        self.resource = resource

    def do(self):
        return self.resource.provide()


class MyContainer(containers.DeclarativeContainer):

    resource = providers.Singleton(
        MyResource,
        value="my value",
    )

    service = providers.Singleton(
        MyService,
        resource=resource,
    )


@inject
def run(service: MyService = Provide[MyContainer.service]):
    return service.do()


def configure_container(container):
    container.wire(modules=[sys.modules[__name__]])


def main():
    container = MyContainer()
    configure_container(container)
    print(run())


if __name__ == '__main__':
    main()

And couple simple tests for it:

# test_app.py

from unittest.mock import MagicMock

import pytest

from my_app import MyContainer
from my_app import configure_container
from my_app import run


@pytest.fixture(scope="session", autouse=True)  # or scope="session"
def container_fixture():
    container = MyContainer()
    configure_container(container)
    return container


def test_1(container_fixture):
    overrided_test_resource = MagicMock()
    overrided_test_resource.provide.return_value = "overrided value"
    with container_fixture.resource.override(overrided_test_resource):
        assert run() == "overrided value"


def test_2():
    assert run() == "my value"

In tests, I want to create a container exactly once and reuse it in each test. In some tests, I want to override the behavior of the container member. But only for one test.

But instead, these overrides are not resetted, and they are applied for next tests.

And I am getting the error:

$ python -m pytest -v
============================= test session starts =============================
platform linux -- Python 3.8.5, pytest-6.2.2, py-1.10.0, pluggy-0.13.1 -- ...
cachedir: .pytest_cache
rootdir: ...
collected 2 items                                                             

tests/test_app.py::test_1 PASSED                                        [ 50%]
tests/test_app.py::test_2 FAILED                                        [100%]

================================== FAILURES ===================================
___________________________________ test_2 ____________________________________

    def test_2():
>       assert run() == "my value"
E       AssertionError: assert 'overrided value' == 'my value'
E         - my value
E         + overrided value

tests/test_app.py:25: AssertionError
=========================== short test summary info ===========================
FAILED tests/test_app.py::test_2 - AssertionError: assert 'overrided value' ...
========================= 1 failed, 1 passed in 0.05s =========================

If pytest.fixture has scope = function then no error will occur.

What can I do to temporarily override the container member using pytest.fixture session = scope?

Used environment:

Python 3.8.5
attrs==20.3.0
dependency-injector==4.29.1
iniconfig==1.1.1
packaging==20.9
pluggy==0.13.1
py==1.10.0
pyparsing==2.4.7
pytest==6.2.2
six==1.15.0
toml==0.10.2

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Comments:5 (3 by maintainers)

github_iconTop GitHub Comments

1reaction
RockBombercommented, Mar 9, 2021

Thanks for the help! I solved it with adding function scope fixture like:

@pytest.fixture(autouse=True)
def reset_singletones(container_fixture):
    with container_fixture.reset_singletons():
        yield
0reactions
robmoorecommented, Feb 12, 2022

I just spent a considerable amount of timing trying to run down this issue. I’d request that this behavior be added to the docs. I’m happy to create a PR if that’s helpful.

Read more comments on GitHub >

github_iconTop Results From Across the Web

python 3.x - Pytest override fixture scope - Stack Overflow
I pytest, we declare the fixture scope (function, module, class, session) at the fixture definition. Is it possible to override that scope ......
Read more >
pytest fixtures: explicit, modular, scalable
Fixtures are created when first requested by a test, and are destroyed based on their scope : function : the default scope, the...
Read more >
pytest Documentation - Read the Docs
session : the fixture is destroyed at the end of the test session. ... the scope of the spawned containers for different environments....
Read more >
Testing Your Django App With Pytest
module run once per module; session run once per session. Note: Default value of scope is function. Example of simple fixture creation: Another ......
Read more >
Python pytest - The Blue Book
fixture () can have the values of function, class, module, or session. Here's a rundown of each scope value: scope='function' : Run once...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found