php – 如何在没有任何实体的情况下测试doctrine EventListener / Subscriber

发布时间:2022-04-30 发布网站:脚本宝典
脚本宝典收集整理的这篇文章主要介绍了php – 如何在没有任何实体的情况下测试doctrine EventListener / Subscriber脚本宝典觉得挺不错的,现在分享给大家,也给大家做个参考。
我创建了一个AudITLOGgerBundle *,它有一个使用Doctrine Events(PRePErsist,preUpdate和preRemove)的服务,以便在audit_log表(AuditLog Entity)中创建一个新条目.

该捆绑包与我的其他捆绑包工作正常,但我想对它进行单元测试并对其进行功能测试.

问题是,为了对AuditLoggerListener函数进行功能测试,我需要至少有两个“假”实体,我可以坚持,更新等.

在这个包中我不知道如何做到一点,因为我只有一个AuditLog实体,我需要使用两个over实体(仅用于测试).

>第一个实体将是“可审计的”(我必须有一个新的条目
audit_log如果我在此实体上执行持久化,更新或删除).
>第二个将是“不可审计的”(我不能有新的条目
在audit_log表中执行持久化,更新或删除
这个实体).*
>这两个实体可以与唯一的EntityClass相关,但不能是AuditLog的实例

这就是我看到持续功能测试的方式:

<?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: Kali\AuditLoggerBundle\EventListener\TablePrefixListener
        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: Kali\AuditLoggerBundle\EventListener\AuditLoggerListener
        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: Kali\AuditLoggerBundle\Entity\AuditLog

监听器:
    

namespace Kali\AuditLoggerBundle\EventListener;

use DateTime;
use Doctrine\ORM\Event\LifecycleEventArgs;
use Doctrine\ORM\EntityManager;
use Doctrine\ORM\Event\PreUpdateEventArgs;
use JMS\Serializer\SerializerInterface;
use Kali\AuditLoggerBundle\Entity\AuditLog;
use Symfony\component\Security\Core\Authentication\Token\Storage\TokenStorage;
use Symfony\Component\Serializer\Encoder\JsonEncoder;

/**
 * Class AuditLoggerListener
 * insert a new entry in audit_log table for every doctrine event
 *
 * @package Kali\AuditLoggerBundle\EventListener
 */
class AuditLoggerListener
{
    /**
     * @VAR TokenStorage
     */
    protected $securityToken;

    /**
     * @var EntityManager
     */
    protected $em;

    /**
     * @var array
     */
    protected $auditableEntities;

    /**
     * @var array
     */
    protected $nonAuditableEntities  = ['Kali\AuditLoggerBundle\Entity\AuditLog'];

    /**
     * @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) &amp;& in_array(get_class($entity),$this->auditableEntities)))
        ) {
            $auditable = true;
        }

        return $auditable;
    }
}

我想测试一下这个监听器的preXXXX函数……
所以,例如,我需要测试当我在假实体上持续存在时(我真的不知道如何模拟),我的audit_log表中有一个新条目…

解决方法

测试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),但他们可能需要更多时间来处理它们.

@H_777_67@

脚本宝典总结

以上是脚本宝典为你收集整理的php – 如何在没有任何实体的情况下测试doctrine EventListener / Subscriber全部内容,希望文章能够帮你解决php – 如何在没有任何实体的情况下测试doctrine EventListener / Subscriber所遇到的问题。

如果觉得脚本宝典网站内容还不错,欢迎将脚本宝典推荐好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。