mirror of
				https://github.com/ets-labs/python-dependency-injector.git
				synced 2025-11-04 09:57:37 +03:00 
			
		
		
		
	Add unit tests for Annotated attribute and argument injection in wiring
This commit is contained in:
		
							parent
							
								
									783b91bf19
								
							
						
					
					
						commit
						770694bdd0
					
				
							
								
								
									
										120
									
								
								tests/unit/samples/wiring/module_annotated.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										120
									
								
								tests/unit/samples/wiring/module_annotated.py
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,120 @@
 | 
				
			||||||
 | 
					"""Test module for wiring with Annotated."""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from decimal import Decimal
 | 
				
			||||||
 | 
					from typing import Callable, Annotated
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from dependency_injector import providers
 | 
				
			||||||
 | 
					from dependency_injector.wiring import inject, Provide, Provider
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from .container import Container, SubContainer
 | 
				
			||||||
 | 
					from .service import Service
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					service: Annotated[Service, Provide[Container.service]]
 | 
				
			||||||
 | 
					service_provider: Annotated[Callable[..., Service], Provider[Container.service]]
 | 
				
			||||||
 | 
					undefined: Annotated[Callable, Provide[providers.Provider()]]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class TestClass:
 | 
				
			||||||
 | 
					    service: Annotated[Service, Provide[Container.service]]
 | 
				
			||||||
 | 
					    service_provider: Annotated[Callable[..., Service], Provider[Container.service]]
 | 
				
			||||||
 | 
					    undefined: Annotated[Callable, Provide[providers.Provider()]]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @inject
 | 
				
			||||||
 | 
					    def __init__(self, service: Annotated[Service, Provide[Container.service]]):
 | 
				
			||||||
 | 
					        self.service = service
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @inject
 | 
				
			||||||
 | 
					    def method(self, service: Annotated[Service, Provide[Container.service]]):
 | 
				
			||||||
 | 
					        return service
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @classmethod
 | 
				
			||||||
 | 
					    @inject
 | 
				
			||||||
 | 
					    def class_method(cls, service: Annotated[Service, Provide[Container.service]]):
 | 
				
			||||||
 | 
					        return service
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @staticmethod
 | 
				
			||||||
 | 
					    @inject
 | 
				
			||||||
 | 
					    def static_method(service: Annotated[Service, Provide[Container.service]]):
 | 
				
			||||||
 | 
					        return service
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@inject
 | 
				
			||||||
 | 
					def test_function(service: Annotated[Service, Provide[Container.service]]):
 | 
				
			||||||
 | 
					    return service
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@inject
 | 
				
			||||||
 | 
					def test_function_provider(service_provider: Annotated[Callable[..., Service], Provider[Container.service]]):
 | 
				
			||||||
 | 
					    service = service_provider()
 | 
				
			||||||
 | 
					    return service
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@inject
 | 
				
			||||||
 | 
					def test_config_value(
 | 
				
			||||||
 | 
					        value_int: Annotated[int, Provide[Container.config.a.b.c.as_int()]],
 | 
				
			||||||
 | 
					        value_float: Annotated[float, Provide[Container.config.a.b.c.as_float()]],
 | 
				
			||||||
 | 
					        value_str: Annotated[str, Provide[Container.config.a.b.c.as_(str)]],
 | 
				
			||||||
 | 
					        value_decimal: Annotated[Decimal, Provide[Container.config.a.b.c.as_(Decimal)]],
 | 
				
			||||||
 | 
					        value_required: Annotated[str, Provide[Container.config.a.b.c.required()]],
 | 
				
			||||||
 | 
					        value_required_int: Annotated[int, Provide[Container.config.a.b.c.required().as_int()]],
 | 
				
			||||||
 | 
					        value_required_float: Annotated[float, Provide[Container.config.a.b.c.required().as_float()]],
 | 
				
			||||||
 | 
					        value_required_str: Annotated[str, Provide[Container.config.a.b.c.required().as_(str)]],
 | 
				
			||||||
 | 
					        value_required_decimal: Annotated[str, Provide[Container.config.a.b.c.required().as_(Decimal)]],
 | 
				
			||||||
 | 
					):
 | 
				
			||||||
 | 
					    return (
 | 
				
			||||||
 | 
					        value_int,
 | 
				
			||||||
 | 
					        value_float,
 | 
				
			||||||
 | 
					        value_str,
 | 
				
			||||||
 | 
					        value_decimal,
 | 
				
			||||||
 | 
					        value_required,
 | 
				
			||||||
 | 
					        value_required_int,
 | 
				
			||||||
 | 
					        value_required_float,
 | 
				
			||||||
 | 
					        value_required_str,
 | 
				
			||||||
 | 
					        value_required_decimal,
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@inject
 | 
				
			||||||
 | 
					def test_config_value_required_undefined(
 | 
				
			||||||
 | 
					        value_required: Annotated[int, Provide[Container.config.a.b.c.required()]],
 | 
				
			||||||
 | 
					):
 | 
				
			||||||
 | 
					    return value_required
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@inject
 | 
				
			||||||
 | 
					def test_provide_provider(service_provider: Annotated[Callable[..., Service], Provide[Container.service.provider]]):
 | 
				
			||||||
 | 
					    service = service_provider()
 | 
				
			||||||
 | 
					    return service
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@inject
 | 
				
			||||||
 | 
					def test_provider_provider(service_provider: Annotated[Callable[..., Service], Provider[Container.service.provider]]):
 | 
				
			||||||
 | 
					    service = service_provider()
 | 
				
			||||||
 | 
					    return service
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@inject
 | 
				
			||||||
 | 
					def test_provided_instance(some_value: Annotated[int, Provide[Container.service.provided.foo["bar"].call()]]):
 | 
				
			||||||
 | 
					    return some_value
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@inject
 | 
				
			||||||
 | 
					def test_subcontainer_provider(some_value: Annotated[int, Provide[Container.sub.int_object]]):
 | 
				
			||||||
 | 
					    return some_value
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@inject
 | 
				
			||||||
 | 
					def test_config_invariant(some_value: Annotated[int, Provide[Container.config.option[Container.config.switch]]]):
 | 
				
			||||||
 | 
					    return some_value
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@inject
 | 
				
			||||||
 | 
					def test_provide_from_different_containers(
 | 
				
			||||||
 | 
					        service: Annotated[Service, Provide[Container.service]],
 | 
				
			||||||
 | 
					        some_value: Annotated[int, Provide[SubContainer.int_object]],
 | 
				
			||||||
 | 
					):
 | 
				
			||||||
 | 
					    return service, some_value
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class ClassDecorator:
 | 
				
			||||||
 | 
					    def __init__(self, fn):
 | 
				
			||||||
 | 
					        self._fn = fn
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def __call__(self, *args, **kwargs):
 | 
				
			||||||
 | 
					        return self._fn(*args, **kwargs)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@ClassDecorator
 | 
				
			||||||
 | 
					@inject
 | 
				
			||||||
 | 
					def test_class_decorator(service: Annotated[Service, Provide[Container.service]]):
 | 
				
			||||||
 | 
					    return service
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def test_container(container: Annotated[Container, Provide[Container]]):
 | 
				
			||||||
 | 
					    return container.service()
 | 
				
			||||||
							
								
								
									
										176
									
								
								tests/unit/wiring/provider_ids/test_main_annotated_py36.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										176
									
								
								tests/unit/wiring/provider_ids/test_main_annotated_py36.py
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,176 @@
 | 
				
			||||||
 | 
					"""Main wiring tests for Annotated attribute and argument injection."""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from decimal import Decimal
 | 
				
			||||||
 | 
					import typing
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from dependency_injector import errors
 | 
				
			||||||
 | 
					from dependency_injector.wiring import Closing, Provide, Provider, wire
 | 
				
			||||||
 | 
					from pytest import fixture, mark, raises
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from samples.wiring import module_annotated as module, package, resourceclosing
 | 
				
			||||||
 | 
					from samples.wiring.service import Service
 | 
				
			||||||
 | 
					from samples.wiring.container import Container, SubContainer
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@fixture(autouse=True)
 | 
				
			||||||
 | 
					def container():
 | 
				
			||||||
 | 
					    container = Container(config={"a": {"b": {"c": 10}}})
 | 
				
			||||||
 | 
					    container.wire(
 | 
				
			||||||
 | 
					        modules=[module],
 | 
				
			||||||
 | 
					        packages=[package],
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					    yield container
 | 
				
			||||||
 | 
					    container.unwire()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@fixture
 | 
				
			||||||
 | 
					def subcontainer():
 | 
				
			||||||
 | 
					    container = SubContainer()
 | 
				
			||||||
 | 
					    container.wire(
 | 
				
			||||||
 | 
					        modules=[module],
 | 
				
			||||||
 | 
					        packages=[package],
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					    yield container
 | 
				
			||||||
 | 
					    container.unwire()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@fixture
 | 
				
			||||||
 | 
					def resourceclosing_container():
 | 
				
			||||||
 | 
					    container = resourceclosing.Container()
 | 
				
			||||||
 | 
					    container.wire(modules=[resourceclosing])
 | 
				
			||||||
 | 
					    yield container
 | 
				
			||||||
 | 
					    container.unwire()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def test_module_attributes_wiring():
 | 
				
			||||||
 | 
					    assert isinstance(module.service, Service)
 | 
				
			||||||
 | 
					    assert isinstance(module.service_provider(), Service)
 | 
				
			||||||
 | 
					    assert isinstance(module.__annotations__['undefined'], typing._AnnotatedAlias)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def test_class_wiring():
 | 
				
			||||||
 | 
					    test_class_object = module.TestClass()
 | 
				
			||||||
 | 
					    assert isinstance(test_class_object.service, Service)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def test_class_wiring_context_arg(container: Container):
 | 
				
			||||||
 | 
					    test_service = container.service()
 | 
				
			||||||
 | 
					    test_class_object = module.TestClass(service=test_service)
 | 
				
			||||||
 | 
					    assert test_class_object.service is test_service
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def test_class_method_wiring():
 | 
				
			||||||
 | 
					    test_class_object = module.TestClass()
 | 
				
			||||||
 | 
					    service = test_class_object.method()
 | 
				
			||||||
 | 
					    assert isinstance(service, Service)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def test_class_classmethod_wiring():
 | 
				
			||||||
 | 
					    service = module.TestClass.class_method()
 | 
				
			||||||
 | 
					    assert isinstance(service, Service)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def test_instance_classmethod_wiring():
 | 
				
			||||||
 | 
					    instance = module.TestClass()
 | 
				
			||||||
 | 
					    service = instance.class_method()
 | 
				
			||||||
 | 
					    assert isinstance(service, Service)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def test_class_staticmethod_wiring():
 | 
				
			||||||
 | 
					    service = module.TestClass.static_method()
 | 
				
			||||||
 | 
					    assert isinstance(service, Service)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def test_instance_staticmethod_wiring():
 | 
				
			||||||
 | 
					    instance = module.TestClass()
 | 
				
			||||||
 | 
					    service = instance.static_method()
 | 
				
			||||||
 | 
					    assert isinstance(service, Service)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def test_class_attribute_wiring():
 | 
				
			||||||
 | 
					    assert isinstance(module.TestClass.service, Service)
 | 
				
			||||||
 | 
					    assert isinstance(module.TestClass.service_provider(), Service)
 | 
				
			||||||
 | 
					    assert isinstance(module.TestClass.__annotations__['undefined'], typing._AnnotatedAlias)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def test_function_wiring():
 | 
				
			||||||
 | 
					    service = module.test_function()
 | 
				
			||||||
 | 
					    assert isinstance(service, Service)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def test_function_wiring_context_arg(container: Container):
 | 
				
			||||||
 | 
					    test_service = container.service()
 | 
				
			||||||
 | 
					    service = module.test_function(service=test_service)
 | 
				
			||||||
 | 
					    assert service is test_service
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def test_function_wiring_provider():
 | 
				
			||||||
 | 
					    service = module.test_function_provider()
 | 
				
			||||||
 | 
					    assert isinstance(service, Service)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def test_function_wiring_provider_context_arg(container: Container):
 | 
				
			||||||
 | 
					    test_service = container.service()
 | 
				
			||||||
 | 
					    service = module.test_function_provider(service_provider=lambda: test_service)
 | 
				
			||||||
 | 
					    assert service is test_service
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def test_configuration_option():
 | 
				
			||||||
 | 
					    (
 | 
				
			||||||
 | 
					        value_int,
 | 
				
			||||||
 | 
					        value_float,
 | 
				
			||||||
 | 
					        value_str,
 | 
				
			||||||
 | 
					        value_decimal,
 | 
				
			||||||
 | 
					        value_required,
 | 
				
			||||||
 | 
					        value_required_int,
 | 
				
			||||||
 | 
					        value_required_float,
 | 
				
			||||||
 | 
					        value_required_str,
 | 
				
			||||||
 | 
					        value_required_decimal,
 | 
				
			||||||
 | 
					    ) = module.test_config_value()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    assert value_int == 10
 | 
				
			||||||
 | 
					    assert value_float == 10.0
 | 
				
			||||||
 | 
					    assert value_str == "10"
 | 
				
			||||||
 | 
					    assert value_decimal == Decimal(10)
 | 
				
			||||||
 | 
					    assert value_required == 10
 | 
				
			||||||
 | 
					    assert value_required_int == 10
 | 
				
			||||||
 | 
					    assert value_required_float == 10.0
 | 
				
			||||||
 | 
					    assert value_required_str == "10"
 | 
				
			||||||
 | 
					    assert value_required_decimal == Decimal(10)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def test_configuration_option_required_undefined(container: Container):
 | 
				
			||||||
 | 
					    container.config.reset_override()
 | 
				
			||||||
 | 
					    with raises(errors.Error, match="Undefined configuration option \"config.a.b.c\""):
 | 
				
			||||||
 | 
					        module.test_config_value_required_undefined()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def test_provide_provider():
 | 
				
			||||||
 | 
					    service = module.test_provide_provider()
 | 
				
			||||||
 | 
					    assert isinstance(service, Service)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def test_provider_provider():
 | 
				
			||||||
 | 
					    service = module.test_provider_provider()
 | 
				
			||||||
 | 
					    assert isinstance(service, Service)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def test_provided_instance(container: Container):
 | 
				
			||||||
 | 
					    class TestService:
 | 
				
			||||||
 | 
					        foo = {"bar": lambda: 10}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    with container.service.override(TestService()):
 | 
				
			||||||
 | 
					        some_value = module.test_provided_instance()
 | 
				
			||||||
 | 
					    assert some_value == 10
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def test_subcontainer():
 | 
				
			||||||
 | 
					    some_value = module.test_subcontainer_provider()
 | 
				
			||||||
 | 
					    assert some_value == 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def test_config_invariant(container: Container):
 | 
				
			||||||
 | 
					    config = {
 | 
				
			||||||
 | 
					        "option": {
 | 
				
			||||||
 | 
					            "a": 1,
 | 
				
			||||||
 | 
					            "b": 2,
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "switch": "a",
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    container.config.from_dict(config)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    value_default = module.test_config_invariant()
 | 
				
			||||||
 | 
					    assert value_default == 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    with container.config.switch.override("a"):
 | 
				
			||||||
 | 
					        value_a = module.test_config_invariant()
 | 
				
			||||||
 | 
					    assert value_a == 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    with container.config.switch.override("b"):
 | 
				
			||||||
 | 
					        value_b = module.test_config_invariant()
 | 
				
			||||||
 | 
					    assert value_b == 2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def test_class_decorator():
 | 
				
			||||||
 | 
					    service = module.test_class_decorator()
 | 
				
			||||||
 | 
					    assert isinstance(service, Service)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def test_container():
 | 
				
			||||||
 | 
					    service = module.test_container()
 | 
				
			||||||
 | 
					    assert isinstance(service, Service)
 | 
				
			||||||
		Loading…
	
		Reference in New Issue
	
	Block a user