php – 如何在没有任何实体的情况下测试doctrine EventListener
我创建了一个AuditLoggerBundle *,它有一个使用Doctrine Events(prePersist,preUpdate和preRemove)的服务,以便在audit_log表(AuditLog Entity)中创建一个新条目.
该捆绑包与我的其他捆绑包工作正常,但我想对它进行单元测试并对其进行功能测试. 问题是,为了对AuditLoggerListener函数进行功能测试,我需要至少有两个“假”实体,我可以坚持,更新等. 在这个包中我不知道如何做到这一点,因为我只有一个AuditLog实体,我需要使用两个over实体(仅用于测试). >第一个实体将是“可审计的”(我必须有一个新的条目 这就是我看到持续功能测试的方式: <?php $animal = new Animal(); //this is a fake Auditable entity $animal->setName('toto'); $em = new EntityManager(); //actually I will use the container to get this manager $em->persist($animal); $em->flush(); //Here we test that I have a new line in audit_log table with the right informations 所以我的问题是我的bundle中没有任何Animal实体,我只需要这个来测试bundle,所以它必须只在测试数据库中创建,而不是在生产环境中创建(当我做app时/ console doctrine:schema:update –force EDIT_1:在阅读完答案后,将对AuditLoggerListener函数进行单元测试,但我仍想进行功能测试 *是的我知道它们有很多,但它们并不符合我的要求. 感谢您的回答,我希望它能帮助一些人! EDIT_2:这是代码 services: #add a prefix to the auditLogger table kali_audit_logger.doctrine.table.prefix: class: KaliAuditLoggerBundleEventListenerTablePrefixListener arguments: [%application.db.table.prefix%] tags: - { name: doctrine.event_listener,event: loadClassMetadata } #audit all doctrine actions made by a user kali_audit_logger.doctrine.event.logger: class: KaliAuditLoggerBundleEventListenerAuditLoggerListener arguments: [@kali_audit_log,@jms_serializer.serializer,@security.token_storage,%application.auditable.entities%,%application.non.auditable.entities%] tags: - { name: doctrine.event_listener,event: prePersist } - { name: doctrine.event_listener,event: preUpdate } - { name: doctrine.event_listener,event: preRemove } # new AuditLog kali_audit_log: class: KaliAuditLoggerBundleEntityAuditLog 监听器: namespace KaliAuditLoggerBundleEventListener; use DateTime; use DoctrineORMEventLifecycleEventArgs; use DoctrineORMEntityManager; use DoctrineORMEventPreUpdateEventArgs; use JMSSerializerSerializerInterface; use KaliAuditLoggerBundleEntityAuditLog; use SymfonyComponentSecurityCoreAuthenticationTokenStorageTokenStorage; use SymfonyComponentSerializerEncoderJsonEncoder; /** * Class AuditLoggerListener * insert a new entry in audit_log table for every doctrine event * * @package KaliAuditLoggerBundleEventListener */ class AuditLoggerListener { /** * @var TokenStorage */ protected $securityToken; /** * @var EntityManager */ protected $em; /** * @var array */ protected $auditableEntities; /** * @var array */ protected $nonAuditableEntities = ['KaliAuditLoggerBundleEntityAuditLog']; /** * @var AuditLog */ protected $auditLogger; /** * @var SerializerInterface */ protected $serializer; /** * @param AuditLog $auditLogger * @param SerializerInterface $serializer * @param TokenStorage $securityToken * @param array $auditableEntities * @param array $nonAuditableEntities */ public function __construct( AuditLog $auditLogger,SerializerInterface $serializer,TokenStorage $securityToken,$auditableEntities = [],$nonAuditableEntities = [] ) { $this->auditLogger = $auditLogger; $this->serializer = $serializer; $this->securityToken = $securityToken; $this->auditableEntities = $auditableEntities; //add all non auditable entities to the current array of non auditable entities array_merge($this->nonAuditableEntities,$nonAuditableEntities); } /** * * @param LifecycleEventArgs $args * * @return boolean */ public function prePersist(LifecycleEventArgs $args) { $this->em = $args->getEntityManager(); $entity = $args->getEntity(); $this->em ->getEventManager() ->removeEventListener('prePersist',$this); if ($this->isAuditableEntity($entity)) { $this->addAudit( $this->securityToken->getToken()->getUsername(),"INSERT",get_class($entity),$this->serializer->serialize($entity,JsonEncoder::FORMAT) ); } return true; } /** * * @param PreUpdateEventArgs $args * * @return boolean */ public function preUpdate(PreUpdateEventArgs $args) { $this->em = $args->getEntityManager(); $entity = $args->getEntity(); $this->em ->getEventManager() ->removeEventListener('preUpdate',"UPDATE",JsonEncoder::FORMAT),$this->serializer->serialize($args->getEntityChangeSet(),JsonEncoder::FORMAT) ); } return true; } /** * * @param LifecycleEventArgs $args * * @return boolean */ public function preRemove(LifecycleEventArgs $args) { $this->em = $args->getEntityManager(); $entity = $args->getEntity(); $this->em ->getEventManager() ->removeEventListener('preRemove',"REMOVE",JsonEncoder::FORMAT) ); } return true; } /** * Insert a new line in audit_log table * * @param string $user * @param string $action * @param string $entityClass * @param null|string $entityValue * @param null|string $entityChange * * @return void */ private function addAudit($user,$action,$entityClass,$entityValue = null,$entityChange = null) { if ($this->auditLogger) { $this->auditLogger ->setUser($user) ->setAction($action) ->setEntityClass($entityClass) ->setEntityValue($entityValue) ->setEntityChange($entityChange) ->setDate(new DateTime()); } if ($this->em) { $this->em->persist($this->auditLogger); $this->em->flush(); } } /** * check if an entity is auditable * * @param $entity * * @return bool */ private function isAuditableEntity($entity) { $auditable = false; //the entity must not be in the non auditable entity array if (!in_array(get_class($entity),$this->nonAuditableEntities) && (empty($this->auditableEntities) || (!empty($this->auditableEntities) && in_array(get_class($entity),$this->auditableEntities))) ) { $auditable = true; } return $auditable; } } 我想测试一下这个监听器的preXXXX函数…… 解决方法
测试php类的单元意味着只测试此类包含的代码而无需任何外部交互.
所以你应该模拟所有外部服务:参见phpunit mock documentation https://phpunit.de/manual/current/en/test-doubles.html#test-doubles.mock-objects 例如,如果您的类看起来像这样: <?php class AuditLogListener { ... function postPersist($event) { $animal = new Animal(); $em = $event->getEm(); $em->persist($animal); } ... } 您的测试应如下所示: <?php class AuditLogListenerTest { private $em; ... function testPostPersist() { $em = $this->getMockBuilder('stdClass') ->setMethods(array('persist')) ->getMock(); $em->expects($this->once()) ->method('persist') ->with($this->isInstanceOf('Animal')); $event = $this->getMockBuilder('stdClass') ->setMethods(array('getEm')) ->getMock(); $event->expects($this->once()) ->method('getEm') ->will($this->returnValue($em)); $listener = new AuditLogListener(); $listener->postPersist($event); } ... } 有更多易于使用的模拟框架,如prophecy(https://github.com/phpspec/prophecy),但他们可能需要更多时间来处理它们. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |