ivankorobkov / python-inject

Python dependency injection
Apache License 2.0
671 stars 77 forks source link

Provisioning a temporary injector in tests. #103

Closed shtlrs closed 1 month ago

shtlrs commented 1 month ago

Currently, the configured injector will be the same throughout the entire application's lifetime, same goes for the tests.

However, some test scenarios might require to inject a more specific Mock for a particular use case.

It would be great to come up with a way to override the "global" injector during the lifetime of a test case, then release it and fallback to the main one once the test case is done.

I haven't looked at the source code just yet, but i think this will greatly increase flexibility when writing tests.

I have had the idea of configuring the injector during setup time then restoring the old one at teardown time, but that seems quite redundant and would be nice to have an out of the box solution for this.

ivankorobkov commented 1 month ago

Hello,

One global instance is a design choice, which simplifies reasoning about the whole application. There is just one object graph at any time.

I would propose several ways for you to have different deps in tests: 1) configure injector for each test. 2) configure injector once for all tests, clean and configure injector for one specific test, but then configure the general one again. 3) wrap a specific dependency into a wrapper with a feature flag, i.e. MockOrRealDB, then set the flag in specific tests db.use_mock = true

shtlrs commented 1 month ago

Hello,

Thanks for. the quick reply.

How do you propose doing step 2 of your suggestion ?

I have mentioned the following in the issue

I have had the idea of configuring the injector during setup time then restoring the old one at teardown time, but that seems quite redundant and would be nice to have an out of the box solution for this.

Is that what you had in mind ?

Thanks again.

ivankorobkov commented 1 month ago

Is that what you had in mind ? I have had the idea of configuring the injector during setup time then restoring the old one at teardown time, but that seems quite redundant and would be nice to have an out of the box solution for this.

Yes, almost. Just clear and configure again.

class MuTestCase(unittest.TestCase):
    def setUp(self):
        inject.clean_and_configure(testConfig)

    def test_one(self):
        pass

    def test_specific(self):
        try:
            inject.clean_and_configure(specificTestConfig)
        finally:
            inject.clean_and_configure(testConfig)
shtlrs commented 1 month ago

Alright, thank you.

I will follow that approach. Cheers