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

Я использую 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() (который сбрасывает кеш объекта инъекций). От слишком поздно setUp() а также tearDown(), поскольку Foo.a уже может быть вызван в Foo.__init__() для каждого из них.

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

1 ответ

Решение

Ты можешь использовать 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)
Другие вопросы по тегам