Как получить область видимости для каждого тестового случая для объектов, внедренных зависимостями в Python? - PullRequest
3 голосов
/ 27 мая 2011

Я использую python-inject , python 2.6 (с unittest2).

У нас есть классы для тестирования, использующие инъекцию, и тестовые случаи, которые также используют те же значения.В настоящее время мы используем inject.appscope, чтобы «синглетонизировать» значения.В противном случае они создаются для каждого пользователя.

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()

В идеале я хотел бы сбрасывать A после каждого тестового прогона, чтобы избежать перекрестного загрязнения.(В настоящее время сделать что-то вроде A.reset () в tearDown () ..)

inject.reqscope поддерживает что-то вроде этого (набор экземпляров локальной области действия), но я действительно не знаю, где вызвать register() & unregister() (который сбрасывает объектный кеш инъекций).Ot слишком поздно в setUp() и tearDown(), поскольку Foo.a уже может быть вызван в Foo.__init__() для каждого из них.

Любые идеи о том, как это сделать, или я должен использовать другой подход

1 Ответ

1 голос
/ 01 июня 2011

Вы можете использовать setUp и tearDown для регистрации / отмены регистрации области, рассматривая каждый вызов метода тестирования как новый "запрос".

Со следующими изменениями ваш тестовый блок проходит:

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()

    ...

И свяжите свой экземпляр A, используя inject.reqscope:

injector = inject.Injector()
injector.bind(A, scope=inject.reqscope)
...