1

对于一个项目,我有一个复杂的主对象,其中包含许多子组件。这些对象的设置由构造函数接口控制,我将其绑定到各种生命周期和工作流事件,如下所示:

@grok.subscribe(schema.ICustomFolder, lifecycleevent.IObjectAddedEvent)
def setup_custom_folder(folder, event):
    interfaces.IConstructor(folder).setup()

@grok.subscribe(schema.ICustomFolder, lifecycleevent.IObjectModifiedEvent)
def setup_custom_folder(folder, event):
    interfaces.IConstructor(folder).update()

我想做的是在依赖事件处理程序的情况下测试构造函数方法。我尝试通过直接创建对象来避免生命周期事件来做到这一点:

def test_custom_item_constructor(self):
    master = createContent('model.master_object', 
        needed_attribute = 2
    )
    folder = createContent('model.custom_folder',
        __parent__ = master
    )
    self.assertEqual(0, len(folder))
    constructor = interfaces.IConstructor(folder)
    constructor.setup()
    self.assertEqual(2, len(folder))

该方法根据主对象上提供的属性在实例setup内创建许多项目。Custom_Folder但是,这是挂起的,我认为这是由于两个对象实际上都不属于该站点,因此没有获取权限。我可以通过将createContent主对象更改为createContentInContainer并将其添加到测试站点的适当部分来实现这一点,但这会触发所有生命周期事件,这些事件最终会执行构造函数调用,这不会让我在其中测试它们隔离。

我已经尝试为此使用模拟对象,但是处理在 Constructor 期间发生的内容创建变得混乱.setup

解决这个问题的最佳方法是什么?

4

1 回答 1

2

我不确定这是否是最好的方法,但我设法通过首先禁用相关的事件处理程序,然后在站点内正确创建内容来获得我想要的结果:

def test_custom_item_constructor(self):
    zope.component.getGlobalSiteManager().unregisterHandler(
        adapters.master.constructor.setup_masterobject,
        required=[schema.IMasterObject, lifecycleevent.IObjectAddedEvent]
    )
    zope.component.getGlobalSiteManager().unregisterHandler(
        adapters.custom.constructor.setup_customfolder,
        required=[schema.ICustomFolder, lifecycleevent.IObjectAddedEvent]
    )
    master = createContentInContainer(self.portal, 'model.master_object', 
        needed_attribute = 2
    )
    folder = createContentInContainer(master, 'model.custom_folder',
        __parent__ = master
    )
    self.assertEqual(0, len(folder))
    constructor = interfaces.IConstructor(folder)
    constructor.setup()
    self.assertEqual(2, len(folder))

这足以解除由添加新主对象触发的事件链。

于 2012-08-09T06:04:18.613 回答