Lightweight dependency injection for pure OOP.
pip install Wyre==0.2.1
Lightweight dependency injection for pure, testable OOP.
Wyre is available on pypi !
Add wyre == 0.2.1
to your requirements.txt
file or just install it with pip install wyre
.
Injecting class dependencies comes in 3 distinct ways :
Wyre allows you to declare the dependencies of a given class using kwargs on a constructor.
A single decorator @inject
does the trick. This is particularly handy when your dependency tree grows large and deep.
For example, this dependency chain : A < B < C < D < E
, would require you to write a = A(B(C(D(E()))))
in order to create an instance of your class.
Using Wyre, you keep :
A()
since it works recursivelyA(b=Mock())
is all you need to mock out dependenciesOk, let's see how to use it.
class C:
name = 'Bob'
class B:
@inject
def __init__(self, other_dependency=C):
self.c = other_dependency
def say_hello(self):
return 'Hello %s !' % self.c.name
class A:
@inject
def __init__(self, dependency=B):
self.b = dependency
def greetings(self):
return self.b.say_hello()
a = A()
a.greetings() # returns 'Hello Bob !'
Since __init__
is decorated with @inject
, B
instance will be created and injected in A
at instantiation time.
If you want to write a test on A
with a real instance of B
, you basically have nothing to do but write the test.
def test_say_hello():
# given
a = A()
# when
result = a.greetings()
# then
assert result == 'Hello !'
If you want to write a test on A
with a mocked instance of B
, you simply provide this mock using A
's constructor.
def test_say_hello():
# given
mocked_b = Mock(spec=B)
mocked_b.greetings.return_value = 'Hi there !'
a = A(dependency=mocked_b)
# when
result = a.greetings()
# then
assert result == 'Hi there !'
Important notes on what @inject
does :
kwargs
, it will be preserved and not overridden by a new instance.InjectionError
will be raised.__init__()
. If you decorate any other function : an InjectionError
will be raised.kwargs
: an InjectionError
will be raised.