我有一个行为,我通过初始化事件监听器添加到所有模型。
// src/Event/InitializeEventListener.php
...
class InitializeEventListener implements EventListenerInterface
{
public function implementedEvents()
{
return [
'Model.initialize' => 'initializeEvent'
];
}
public function initializeEvent(Event $event, $data = [], $options = [])
{
$event->subject()->addBehavior('MyBehavior');
}
}
// bootstrap.php
$ieListener = new InitializeEventListener();
EventManager::instance()->on($ieListener);
我有UsersController
和index
行动。如果我放debug($this->Users->behaviors()->loaded());die;
,我可以看到默认的Timestamp
和加载的MyBehavior
。到目前为止一切正常,我可以在索引操作中使用MyBehavior
函数。这是在浏览器中打开页面时。
现在,我有这个测试功能
// tests/TestCase/Controller/UsersControllerTest.php
public function testIndex()
{
$this->get('/users/index');
$this->assertResponseSuccess();
}
但是,在运行测试时,MyBehavior
没有被加载(它不在加载的行为列表中,因此使用它的tyring函数会给出未知的方法错误)。我尝试将其添加到UsersController的测试用例
public function setUp()
{
parent::setUp();
$this->Users = TableRegistry::get('Users');
$eventList = new EventList();
$eventList->add(new Event('Users.initializeEvent'));
$this->Users->eventManager()->setEventList($eventList);
}
但未加载MyBehavior
。
由于
答案 0 :(得分:1)
问题是CakePHP测试用例在setup上设置了一个新的全局事件管理器实例:
public function setUp()
{
// ...
EventManager::instance(new EventManager());
}
<强> https://github.com/cakephp/cakephp/blob/3.2.12/src/TestSuite/TestCase.php#L106 强>
因此,在此之前添加到全局事件管理器的所有内容都将丢失。
这是为了避免状态。如果不能完成,那么测试方法A中测试代码添加到全局管理器的可能的监听器仍然会出现在测试方法B中,这当然会导致在那里测试的代码出现问题,比如听众堆叠,导致多次调用它们,调用通常不会被调用的侦听器等。
每当我需要gloabl事件时,我会将它们存储在配置值中,并在测试用例中的设置时应用它们,这些都是
<强>自举强>
$globalListeners = [
new SomeListener(),
new AnotherListener(),
];
Configure::write('App.globalListeners', $globalListeners);
foreach ($globalListeners as $listener) {
EventManager::instance()->on($listener);
}
测试用例基类
public function setUp()
{
parent::setUp();
foreach (Configure::read('App.globalListeners') as $listener) {
EventManager::instance()->on($listener);
}
}
话虽如此,您的设置代码段的问题是
它与侦听事件无关,而是跟踪调度事件。此外,您的应用中可能没有Users.initializeEvent
个事件,至少是InitializeEventListener
代码建议的内容。
实例化一个表类会导致Model.initialize
事件被触发,所以即使你之后正确添加了你的监听器,它也永远不会被触发,除非你已经清除了表注册表,所以用户表将在下一次get()
调用时新构建。