def test_big_dependency_tree(): metrics = MagicMock() container = Container() container.set_metrics(metrics) container.register(Settings, value=object()) container.register(OneCustomType, value=OneCustomType(object)) container.register(TwoCustomType, value=TwoCustomType(object)) container.register(ThreeCustomType, value=ThreeCustomType(object)) container.register(FourCustomType, value=FourCustomType(object)) container.register(FiveCustomType, value=FiveCustomType(object)) container.register(AbstractService, factory=ImplementationService) @container.inject def set_values( param1: int, d1: ServiceOne = Depends(ServiceOne), d2: MyMainClass = Depends(MyMainClass), d3: AnotherMainClass = Depends(AnotherMainClass), ) -> None: ... for _ in range(10): set_values(1) calls = metrics.save_metric.mock_calls assert calls
def test_sub_container(): class Dependency(Protocol): x: int class Dependency1: x = 1 class Dependency2: x = 2 class Client: def __init__(self, dependency: Dependency) -> None: self.x = dependency.x container = Container() sub_container = container.sub_container() sub_container.register(Dependency, value=Dependency1()) with pytest.raises(ResolverError) as e: container.resolve(Client) client1 = sub_container.resolve(Client) assert client1.x == 1 container.register(Dependency, value=Dependency2()) client2 = container.resolve(Client) assert client2.x == 2
def test_container_clear() -> None: test_callable = MagicMock() class Dependency: def __init__(self): test_callable() class Client: def __init__(self, dep: Dependency): ... container = Container() container.resolve(Dependency) test_callable.assert_called_once() container.resolve(Dependency) test_callable.assert_called_once() container.clear() container.resolve(Dependency) test_callable.assert_has_calls([call(), call()]) container.resolve(Dependency) test_callable.assert_has_calls([call(), call()])
def test_preload(): container = Container() m1, m2, m3 = MagicMock(), MagicMock(), MagicMock() class B: def __init__(self) -> None: m1() class C: def __init__(self) -> None: m2() class A: def __init__(self, b: B, c: C) -> None: m3() @container.inject def my_function(dependency=Depends(A)) -> None: ... @container.inject def another_function(dependency=Depends(B)) -> None: ... @container.inject def and_another_function(dependency=Depends(C)) -> None: ... container.preload_injected() m1.assert_has_calls([call(), call()]) m2.assert_has_calls([call(), call()]) m3.assert_has_calls([call()])
def test_cache_thread_safety(): test_fn = MagicMock() class Dependency: def __init__(self): sleep(0.1) test_fn() container = Container() @container.inject def function(d: Dependency = Depends(Dependency)): ... threads = [] for _ in range(10): thread = Thread(target=function) threads.append(thread) thread.start() for thread in threads: thread.join() test_fn.assert_called_once()
def test_basic_register_resolve(): class TestDependency: def __init__(self): self.x = 1 container = Container() container.register(TestDependency) assert container.resolve(TestDependency).x == 1
def test_resolving_with_wrong_parameters(): class Dependency: x = 1 class Client: def __init__(self, dependency: Dependency) -> None: self._dependency = dependency container = Container() with pytest.raises(ResolverError): client = container.resolve(Client, non_existing_parameter=Dependency())
def test_resolve_with_default_values_override_with_parameters(): class Dependency: def __init__(self, x: int = 1): self.x = x class Service: def __init__(self, dependency: Dependency, value: int = 1): self.x = dependency.x + value container = Container() service = container.resolve(Service, value=2) assert service.x == 3
def test_new_type_properly_set() -> None: container = Container() MyType = NewType("MyType", int) my_type_value = MyType(1) container.register(MyType, value=my_type_value) class MyService: def __init__(self, my_type: MyType) -> None: self.my_type = my_type instance = container.resolve(MyService) assert instance.my_type == my_type_value
def test_decorator_dependency(): class Dependency: def __init__(self): self.x = 1 container = Container() @container.inject def my_function( value: int, dependency: Dependency = Depends(Dependency)) -> int: return value + dependency.x assert my_function(value=1) == 2
def test_simple_hierarchy_depedency(): class TestDependency: def __init__(self): self.x = 1 class AnotherTestDependency: def __init__(self, dependency: TestDependency): self.x = dependency.x + 1 container = Container() container.register(AnotherTestDependency) assert container.resolve(AnotherTestDependency).x == 2
def test_dependency_without_registered_dependencies(): class TestDependency: def __init__(self): self.x = 1 container = Container() dependency_1 = container.resolve(TestDependency) dependency_2 = container.resolve(TestDependency) assert dependency_1.x == 1 assert dependency_2.x == 1 assert dependency_1 is dependency_2
def test_register_dependency_with_default_value(): class TestDependency: def __init__(self, x): self.x = x class AnotherTestDependency: def __init__(self, dependency: TestDependency): self.x = dependency.x + 1 container = Container() container.register(TestDependency, value=TestDependency(x=2)) assert container.resolve(AnotherTestDependency).x == 3
def test_sub_container(): os.environ["test"] = "test" class MySettings(BaseSettings): test: str class Client: def __init__(self, settings: MySettings) -> None: self.settings_test = settings.test container = Container() client = container.resolve(Client) assert client.settings_test == "test"
def test_multiple_basic_register_resolve(): class TestDependency: def __init__(self): self.x = 1 class AnotherTestDependency: def __init__(self): self.x = 2 container = Container() container.register(TestDependency) container.register(AnotherTestDependency) assert container.resolve(TestDependency).x == 1 assert container.resolve(AnotherTestDependency).x == 2
def test_register_dependency_by_factory(): class Dependency: def __init__(self, x): self.x = x def dependency_factory() -> Dependency: return Dependency(1) class AnotherDependency: def __init__(self, dependency: Dependency): self.x = dependency.x container = Container() container.register(Dependency, factory=dependency_factory) assert container.resolve(AnotherDependency).x == 1
def test_simple_hierarchy_depedency_without_registerd_dependency(): class TestDependency: def __init__(self): self.x = 1 class AnotherTestDependency: def __init__(self, dependency: TestDependency): self.x = dependency.x + 1 container = Container() dependency_1 = container.resolve(AnotherTestDependency) dependency_2 = container.resolve(AnotherTestDependency) assert dependency_1 is dependency_2 assert dependency_1.x == 2
def test_decorator_dependency_with_mixed_arguments(): class Dependency: def __init__(self): self.x = 1 container = Container() @container.inject def my_function(p1: int, p2: int, p3: int, p4: int, dep: Dependency = Depends(Dependency)) -> int: return p1 + p2 + dep.x + p3 + p4 assert my_function(1, 2, 3, p4=4) == 11 assert my_function(1, p3=2, p2=3, p4=4) == 11
def test_sub_container_2(): class Dependency(Protocol): x: int class Dependency1: x = 1 class Client: def __init__(self, dependency: Dependency) -> None: self.x = dependency.x container = Container() container.register(Dependency, value=Dependency1()) sub_container = container.sub_container() client = sub_container.resolve(Client) assert client.x == 1
def test_value_and_factory_register_exception(): class Dependency: def __init__(self, x): self.x = x def dependency_factory() -> Dependency: return Dependency(1) class AnotherDependency: def __init__(self, dependency: Dependency): self.x = dependency.x container = Container() with pytest.raises(ContainerRegisterError): container.register(Dependency, factory=dependency_factory, value=Dependency(2))
def test_missing_dependencies() -> None: class Dependency: ... class Client: def __init__(self, dep: Dependency, unknown_dep): ... def function(dep: Client, unknown_param): ... container = Container() with pytest.raises(ResolverError, match="Can resolve dependencies for"): container.resolve(Client) with pytest.raises(ResolverError, match="Can resolve dependencies for"): container.resolve(function)
def test_inject_scoped(): test_fn = MagicMock() class Dependency: def __init__(self): test_fn() container = Container() @container.inject_scoped def function(d: Dependency = Depends(Dependency)): ... test_fn.assert_not_called() function() test_fn.assert_called_once() function() test_fn.assert_has_calls([call(), call()])
def test_dummy_celery_injector(): container = Container() class Dependency: def __init__(self): self.x = 1 class Celery: def task(self, fn): return fn celery = Celery() @celery_task(celery, container) def my_function(dependency: Dependency = Depends(Dependency)): return dependency.x assert my_function() == 1
def test_multiple_dependencies(): class Dependency1: def __init__(self): self.x = 1 class Dependency2: def __init__(self): self.x = 2 class Dependency3: def __init__(self, dependency: Dependency1): self.x = dependency.x + 1 class Dependency4: def __init__(self, dependency_3: Dependency3, dependency_2: Dependency2): self.x = dependency_3.x + dependency_2.x container = Container() assert container.resolve(Dependency4).x == 4
def test_metrics(): metrics = MagicMock() container = Container(metrics=metrics) class B: ... class C: ... class A: def __init__(self, b: B, c: C) -> None: ... @container.inject def my_function(dependency=Depends(A)) -> None: ... for _ in range(100): my_function() assert metrics.save_metric.mock_calls
def test_more_complex_example(): class Dependency: x = 1 def factory(): return 1 Dep = NewType("Dep", int) class Client: def __init__(self, dep1: Dependency, dep2: Dep) -> None: self.dep1 = dep1 self.dep2 = dep2 container = Container() container.register(Dep, factory=factory) container.register(Dependency, value=Dependency()) client = container.resolve(Client) assert client.dep1.x == 1 assert client.dep2 == 1
def test_resolving_with_parameters(): class FirstDependency: x = 1 class Dependency(Protocol): y: int class ConcreteDependency: y = 2 class Client: def __init__(self, first_dependency: FirstDependency, second_dependency: Dependency) -> None: self.x = first_dependency.x self.y = second_dependency.y def add(self) -> int: return self.x + self.y container = Container() client = container.resolve(Client, second_dependency=ConcreteDependency) assert client.add() == 3