Symfony/Doctrine事件侦听器仅在任何Unitest中的第一个时才触发
我在说学说听众的“我会变得疯狂”问题。
迅速总结了行为: 需要刷新所有aquired的摘要。
- 当创建1个用户
- 时,
- 我
- 2 仅案件。
我有一个关于Thoose实体的活动听众,以派遣消息来重新计算摘要。 这是设置的方式。
services.yaml
App\EventListener\DroitResume\ListenerOne:
tags:
- { name: 'doctrine.orm.entity_listener', event: 'postPersist', entity: 'App\Entity\Auth\UserAccount', method: 'postPersistUserAccount', lazy: true}
- { name: 'doctrine.orm.entity_listener', event: 'postPersist', entity: 'App\Entity\Auth\UserRight', method: 'postChangeUserRight', lazy: true}
- { name: 'doctrine.orm.entity_listener', event: 'postPersist', entity: 'App\Entity\Auth\UserProfileRight', method: 'postChangeUserProfileRight', lazy: true}
App\EventListener\DroitResume\ListenerTwo:
tags:
- { name: 'doctrine.orm.entity_listener', event: 'postPersist', entity: 'App\Entity\Auth\UserAccount', method: 'postPersistUserAccount', lazy: true}
第二个侦听器是出于演示/测试目的,通常只有一个。
ListenerOne.php
class ListenerOne
{
private MessageBusInterface $messageBus;
public function __construct(MessageBusInterface $messageBus)
{
$this->messageBus = $messageBus;
}
public function postChangeUserRight(UserRight $userRight): void
{
print "ListenerOne => dispatch postChangeUserRight\n";
$this->messageBus->dispatch(new UserRefreshResumeRightsMessage($userRight->getUserAccount()->getId()));
}
public function postChangeUserProfileRight(UserProfileRight $userProfileRight): void
{
print "ListenerOne => dispatch postChangeUserProfileRight\n";
$this->messageBus->dispatch(new ProfileRefreshResumeRightsMessage($userProfileRight->getUserProfile()->getId()));
}
public function postPersistUserAccount(UserAccount $userAccount)
{
print "ListenerOne => dispatch postPersistUserAccount\n";
$this->messageBus->dispatch(new UserRefreshResumeRightsMessage($userAccount->getId()));
}
}
ListenerTwo.php
class ListenerTwo
{
private MessageBusInterface $messageBus;
public function __construct(MessageBusInterface $messageBus)
{
$this->messageBus = $messageBus;
}
public function postPersistUserAccount(UserAccount $userAccount)
{
print "ListenerTwo => dispatch postPersistUserAccount\n";
$this->messageBus->dispatch(new UserRefreshResumeRightsMessage($userAccount->getId()));
}
}
然后,
RefreshRightTest.php
class RefreshRightTest extends MyTestCase { //MyTestCase extends KernelTestCase and add some usefull methods
public function testPersistUserOne() {
$em = $this->getEntityManager();
$user = new UserAccount();
$user->setName('blabla One');
$user->setEmail('[email protected]');
print "Persist User Blabla One\n";
$em->persist($user);
$em->flush();
$user = new UserAccount();
$user->setName('blabla Two');
$user->setEmail('[email protected]');
print "Persist User Blabla Two\n";
$em->persist($user);
$em->flush();
}
public function testPersistUserRightOne() {
$em = $this->getEntityManager();
$user = $this->getExistingUserFromName('Existing User One');
$userRight = new UserRight();
$userRight->setUserAccount($user);
$userRight->setRightKey('RIGHT_ONE');
$userRight->setValue(1);
print "Persist UserRight One\n";
$em->persist($userRight);
$em->flush();
}
public function testPersistUserTwo() {
$em = $this->getEntityManager();
$user = new UserAccount();
$user->setName('blabla Three');
$user->setEmail('[email protected]');
print "Persist User Blabla Three\n";
$em->persist($user);
$em->flush();
}
public function testPersistUserRightTwo() {
$em = $this->getEntityManager();
$user = $this->getExistingUserFromName('Existing User Two');
$userRight = new UserRight();
$userRight->setUserAccount($user);
$userRight->setRightKey('RIGHT_ANY');
$userRight->setValue(2);
print "Persist UserRight Two\n";
$em->persist($userRight);
$em->flush();
}
}
当我运行测试时,请在此处进行单元测试:
Persist User Blabla One
ListenerOne => dispatch postPersistUserAccount
ListenerTwo => dispatch postPersistUserAccount
Persist User Blabla Two
ListenerOne => dispatch postPersistUserAccount
ListenerTwo => dispatch postPersistUserAccount
Persist UserRight One
ListenerOne => dispatch postChangeUserRight
Persist User Blabla Three
Persist UserRight Two
ListenerOne => dispatch postChangeUserRight
正如您可以看到的,只有在第一个测试中,才会触发p.persistuseraccount侦听器。 一旦触发了任何其他听众,它就不会再触发了。 我可以在ChangeSright或PostchangeUserProfileright上进行任何数量的测试,它们将始终触发。但是,pickpersistuseraccount上的任何听众都不会触发过去的第一次测试。
我没有任何thoose实体的名人。 我在代码中任何地方都没有任何停止传播。 实体之间的唯一区别是,用户accout实现用户接口(因为它是我的用户表)
以前有人遇到过类似的东西。我已经尽一切可能尝试找到正在发生的事情,但是还没有一致的出现。
测试顺序运行的一些看法:
T1: persist UserAccount
T2: persist UserRight
T3: persist UserAccount
=> postPersistUserAccount only triggers on T1
T1: persist UserRight
T2: persist UserAccount
T3: persist UserAccount
T4: persist UserRight
=> postPersistUserAccount never triggers, postPersistUserRight triggers ont Tests 1 and 4 as intended
I'm encoutering a "Im going to turn mad" problem with doctrine listeners.
Quickly summed up behavior:
I need to refresh a summary of all aquired right when:
- 1 A user is created
- 2 A right is added to the user
- 3 A riht is added to a profile linked to the user
- 4 others on updates but we can trigger the bug with these use case only.
I have an event listener on thoose entities to dispatch a message to re-compute the summary.
Here's how it's setup.
services.yaml
App\EventListener\DroitResume\ListenerOne:
tags:
- { name: 'doctrine.orm.entity_listener', event: 'postPersist', entity: 'App\Entity\Auth\UserAccount', method: 'postPersistUserAccount', lazy: true}
- { name: 'doctrine.orm.entity_listener', event: 'postPersist', entity: 'App\Entity\Auth\UserRight', method: 'postChangeUserRight', lazy: true}
- { name: 'doctrine.orm.entity_listener', event: 'postPersist', entity: 'App\Entity\Auth\UserProfileRight', method: 'postChangeUserProfileRight', lazy: true}
App\EventListener\DroitResume\ListenerTwo:
tags:
- { name: 'doctrine.orm.entity_listener', event: 'postPersist', entity: 'App\Entity\Auth\UserAccount', method: 'postPersistUserAccount', lazy: true}
Second listener is here for demonstration/test purpose, usualcode only has one.
ListenerOne.php
class ListenerOne
{
private MessageBusInterface $messageBus;
public function __construct(MessageBusInterface $messageBus)
{
$this->messageBus = $messageBus;
}
public function postChangeUserRight(UserRight $userRight): void
{
print "ListenerOne => dispatch postChangeUserRight\n";
$this->messageBus->dispatch(new UserRefreshResumeRightsMessage($userRight->getUserAccount()->getId()));
}
public function postChangeUserProfileRight(UserProfileRight $userProfileRight): void
{
print "ListenerOne => dispatch postChangeUserProfileRight\n";
$this->messageBus->dispatch(new ProfileRefreshResumeRightsMessage($userProfileRight->getUserProfile()->getId()));
}
public function postPersistUserAccount(UserAccount $userAccount)
{
print "ListenerOne => dispatch postPersistUserAccount\n";
$this->messageBus->dispatch(new UserRefreshResumeRightsMessage($userAccount->getId()));
}
}
ListenerTwo.php
class ListenerTwo
{
private MessageBusInterface $messageBus;
public function __construct(MessageBusInterface $messageBus)
{
$this->messageBus = $messageBus;
}
public function postPersistUserAccount(UserAccount $userAccount)
{
print "ListenerTwo => dispatch postPersistUserAccount\n";
$this->messageBus->dispatch(new UserRefreshResumeRightsMessage($userAccount->getId()));
}
}
Then thoose unit tests
RefreshRightTest.php
class RefreshRightTest extends MyTestCase { //MyTestCase extends KernelTestCase and add some usefull methods
public function testPersistUserOne() {
$em = $this->getEntityManager();
$user = new UserAccount();
$user->setName('blabla One');
$user->setEmail('[email protected]');
print "Persist User Blabla One\n";
$em->persist($user);
$em->flush();
$user = new UserAccount();
$user->setName('blabla Two');
$user->setEmail('[email protected]');
print "Persist User Blabla Two\n";
$em->persist($user);
$em->flush();
}
public function testPersistUserRightOne() {
$em = $this->getEntityManager();
$user = $this->getExistingUserFromName('Existing User One');
$userRight = new UserRight();
$userRight->setUserAccount($user);
$userRight->setRightKey('RIGHT_ONE');
$userRight->setValue(1);
print "Persist UserRight One\n";
$em->persist($userRight);
$em->flush();
}
public function testPersistUserTwo() {
$em = $this->getEntityManager();
$user = new UserAccount();
$user->setName('blabla Three');
$user->setEmail('[email protected]');
print "Persist User Blabla Three\n";
$em->persist($user);
$em->flush();
}
public function testPersistUserRightTwo() {
$em = $this->getEntityManager();
$user = $this->getExistingUserFromName('Existing User Two');
$userRight = new UserRight();
$userRight->setUserAccount($user);
$userRight->setRightKey('RIGHT_ANY');
$userRight->setValue(2);
print "Persist UserRight Two\n";
$em->persist($userRight);
$em->flush();
}
}
Here the console output when I run the tests:
Persist User Blabla One
ListenerOne => dispatch postPersistUserAccount
ListenerTwo => dispatch postPersistUserAccount
Persist User Blabla Two
ListenerOne => dispatch postPersistUserAccount
ListenerTwo => dispatch postPersistUserAccount
Persist UserRight One
ListenerOne => dispatch postChangeUserRight
Persist User Blabla Three
Persist UserRight Two
ListenerOne => dispatch postChangeUserRight
As you can see postPersistUserAccount listeners are only triggered if it's in the first test.
As soon as any other listener is triggered it never triggers again.
I can run any amount of tests on postChangeUserRight or postChangeUserProfileRight they will always trigger. But any listener on postPersistUserAccount won't trigger past first test is run.
I don't have any other listner on any of thoose entities.
I don't have any stop propagation anywhere in the code.
The only difference between entities is that UserAccout implements UserInterface (as it's my users table)
Has anyone encountered something similar before. I've tried everything I can to try and find what's happening, but nothing consistent as emerged yet.
Some exemples of test order run:
T1: persist UserAccount
T2: persist UserRight
T3: persist UserAccount
=> postPersistUserAccount only triggers on T1
T1: persist UserRight
T2: persist UserAccount
T3: persist UserAccount
T4: persist UserRight
=> postPersistUserAccount never triggers, postPersistUserRight triggers ont Tests 1 and 4 as intended
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论