I'm using python-inject, python 2.6 (with unittest2).
We have classes to test that use injection, and test-cases which also use the same values. We currently use inject.appscope, to "singletonize" the values. Otherwise they're instantiated per user.
import inject
class A(object):
'''shared data between many parts'''
...
class Foo(object):
'''uses a to do stuff'''
a = inject.attr('a', A)
def bar(self):
self.a.doStuff()
class TestFoo(TestCase):
a = inject.attr('a', A)
def setUp(self):
self.foo = Foo()
def testBar(self):
self.foo.bar()
self.assertTrue(self.a.stuffWasDone())
self.assertFalse(self.a.stuffWasDoneTwice())
def testBarTwice(self):
self.foo.bar()
self.foo.bar()
self.assertTrue(self.a.stuffWasDoneTwice())
injector = inject.Injector()
injector.bind(A, scope=inject.appscope)
inject.register(injector)
runTests()
Ideally, I'd like to reset A after each test run, to avoid cross-contamination. (Currently do something like A.reset() in tearDown()..)
inject.reqscope
supports something like this (a locally scoped set of instances), but I don't really know where to call register()
& unregister()
(which resets the injection objet cache). Ot's too late in setUp()
and tearDown()
, since Foo.a may already be called in Foo.__init__()
for each of them.
Any ideas on how to do this, or should I use a different approach?
You can use setUp
and tearDown
to register/unregister the scope, treating each test method invocation as a new "request".
With the following changes your sample unit tests pass:
class TestFoo(unittest2.TestCase):
a = inject.attr('a', A)
def __init__(self, *n, **kw):
unittest2.TestCase.__init__(self, *n, **kw)
self.unit_scope = inject.reqscope
def setUp(self):
self.foo = Foo()
self.unit_scope.register()
def tearDown(self):
self.unit_scope.unregister()
...
And bind your A
instance using inject.reqscope
:
injector = inject.Injector()
injector.bind(A, scope=inject.reqscope)