php - Zend Framework 2 - 如何对自己的 session 服务进行单元测试?

标签 php unit-testing session service zend-framework2

我在对自己的 SessionManager 服务进行单元测试时遇到问题。我在单元测试中没有错误,但 session 未在数据库中创建,我无法写入存储。这是我的代码:

session 管理器工厂:

namespace Admin\Service;

use Zend\ServiceManager\FactoryInterface;
use Zend\ServiceManager\ServiceLocatorInterface;
use Zend\ServiceManager\ServiceManager;
use Zend\Session\SaveHandler\DbTableGatewayOptions as SessionDbSavehandlerOptions;
use Zend\Session\SaveHandler\DbTableGateway;
use Zend\Session\Config\SessionConfig;
use Zend\Session\SessionManager;
use Zend\Db\TableGateway\TableGateway;

class SessionManagerFactory implements FactoryInterface
{
    public function createService(ServiceLocatorInterface $serviceLocator)
    {
        return $this;
    }

    public function setUp(ServiceManager $serviceManager)
    {
        $sessionOptions = new SessionDbSavehandlerOptions();
        $sessionOptions->setDataColumn('data')
                       ->setIdColumn('id')
                       ->setModifiedColumn('modified')
                       ->setLifetimeColumn('lifetime')
                       ->setNameColumn('name');
        $dbAdapter = $serviceManager->get('Zend\Db\Adapter\Adapter');
        $sessionTableGateway = new TableGateway('zf2_sessions', $dbAdapter);
        $sessionGateway = new DbTableGateway($sessionTableGateway, $sessionOptions);
        $config = $serviceManager->get('Configuration');
        $sessionConfig = new SessionConfig();
        $sessionConfig->setOptions($config['session']);
        $sessionManager = new SessionManager($sessionConfig);
        $sessionManager->setSaveHandler($sessionGateway);

        return $sessionManager;
    }
}
Admin 命名空间中 Module.php

GetServiceConfig() 方法:

public function getServiceConfig()
    {
        return array(
            'factories' => array(
                'Zend\Authentication\Storage\Session' => function($sm) {
                    return new StorageSession();
                },
                'AuthService' => function($sm) {
                    $dbAdapter = $sm->get('Zend\Db\Adapter\Adapter');
                    $authAdapter = new AuthAdapter($dbAdapter, 'zf2_users', 'email', 'password');

                    $authService = new AuthenticationService();
                    $authService->setAdapter($authAdapter);
                    $authService->setStorage($sm->get('Zend\Authentication\Storage\Session'));

                    return $authService;
                },
                'SessionManager' => function($serviceManager){
                    $sessionManager = new SessionManagerFactory();
                    return $sessionManager->setUp($serviceManager);
                }
            )
        );
    }

和来自单元测试文件的setUp()方法:

protected function setUp()
    {
        $bootstrap             = \Zend\Mvc\Application::init(include 'config/app.config.php');
        $this->controller      = new SignController;
        $this->request         = new Request;
        $this->routeMatch      = new RouteMatch(array('controller' => 'sign'));
        $this->event           = $bootstrap->getMvcEvent();

        // Below line should start session and storage it in Database. 
        $bootstrap->getServiceManager()->get('SessionManager')->start();
        // And this line should add test variable to default namespace of session, but doesn't - blow line is only for quick test. I will write method for test write to storage.
        Container::getDefaultManager()->test = 12;

        $this->event->setRouteMatch($this->routeMatch);
        $this->controller->setEvent($this->event);
        $this->controller->setEventManager($bootstrap->getEventManager());
        $this->controller->setServiceLocator($bootstrap->getServiceManager());
    }

如何测试此服务以及为什么未创建 session ?

最佳答案

我认为您误解了工厂模式。您的工厂应如下所示。据我所知,在任何地方都不会调用单独的 setUp 方法。您不会在任何地方手动调用它。

class SessionManagerFactory implements FactoryInterface
{
    public function createService(ServiceLocatorInterface $serviceLocator)
    {
        $sessionOptions = new SessionDbSavehandlerOptions();
        $sessionOptions->setDataColumn('data')
                       ->setIdColumn('id')
                       ->setModifiedColumn('modified')
                       ->setLifetimeColumn('lifetime')
                       ->setNameColumn('name');
        $dbAdapter = $serviceManager->get('Zend\Db\Adapter\Adapter');
        $sessionTableGateway = new TableGateway('zf2_sessions', $dbAdapter);
        $sessionGateway = new DbTableGateway($sessionTableGateway, $sessionOptions);
        $config = $serviceManager->get('Configuration');
        $sessionConfig = new SessionConfig();
        $sessionConfig->setOptions($config['session']);
        $sessionManager = new SessionManager($sessionConfig);
        $sessionManager->setSaveHandler($sessionGateway);

        return $sessionManager;

    }

}

以下所有代码都适合我。我认为您还缺少其他一些东西,但以上内容应该可以解决。寻找下面的 SEE ME 评论。另外,像下面一样向您的 Module.php 添加一个 onBootstrap 方法,并确保在您的情况下调用 $sessionManager = $serviceManager->get( 'SessionManager' ); 这样您的 SessionFactory 就是实际上调用。您已经在单元测试的 setup() 函数中调用了它,但如果您在模块中调用它,您就不必自己手动调用它。

在 application.config 我有这个

'session' => array(
        'name'                => 'PHPCUSTOM_SESSID',
        'cookie_lifetime'     => 300, //1209600, //the time cookies will live on user browser
        'remember_me_seconds' => 300, //1209600 //the time session will live on server
        'gc_maxlifetime'      => 300
    )
'db' => array(
        'driver' => 'Pdo_Sqlite',
        'database' => '/tmp/testapplication.db'
    ),

我的 session 工厂非常相似,但我多了一行代码。查找评论。

use Zend\ServiceManager\FactoryInterface,
    Zend\ServiceManager\ServiceLocatorInterface,
    Zend\Session\SessionManager,
    Zend\Session\Config\SessionConfig,
    Zend\Session\SaveHandler\DbTableGateway as SaveHandler,
    Zend\Session\SaveHandler\DbTableGatewayOptions as SaveHandlerOptions,
    Zend\Db\Adapter\Adapter,
    Zend\Db\TableGateway\TableGateway;

class SessionFactory
    implements FactoryInterface
{

    public function createService( ServiceLocatorInterface $sm )
    {
        $config = $sm->has( 'Config' ) ? $sm->get( 'Config' ) : array( );
        $config = isset( $config[ 'session' ] ) ? $config[ 'session' ] : array( );
        $sessionConfig = new SessionConfig();
        $sessionConfig->setOptions( $config );

        $dbAdapter = $sm->get( '\Zend\Db\Adapter\Adapter' );

        $sessionTableGateway = new TableGateway( 'sessions', $dbAdapter );
        $saveHandler = new SaveHandler( $sessionTableGateway, new SaveHandlerOptions() );

        $manager = new SessionManager();
        /******************************************/
        /* SEE ME : I DON'T SEE THE LINE BELOW IN YOUR FACTORY. It probably doesn't matter though. 
        /******************************************/

        $manager->setConfig( $sessionConfig );  
        $manager->setSaveHandler( $saveHandler );

        return $manager;
    }

在我的一个模块中,我有以下内容

public function onBootstrap( EventInterface $e )
    {

        // You may not need to do this if you're doing it elsewhere in your
        // application
        /* @var $eventManager \Zend\EventManager\EventManager  */
        /* @var $e \Zend\Mvc\MvcEvent */
        $eventManager = $e->getApplication()->getEventManager();

        $serviceManager = $e->getApplication()->getServiceManager();

        $moduleRouteListener = new ModuleRouteListener();
        $moduleRouteListener->attach( $eventManager );

        try
        {
            //try to connect to the database and start the session
            /* @var $sessionManager SessionManager */
            $sessionManager = $serviceManager->get( 'Session' );

            /******************************************/
            /* SEE ME : Make sure to start the session
            /******************************************/
            $sessionManager->start();
        }
        catch( \Exception $exception )
        {
            //if we couldn't connect to the session then we trigger the
            //error event
            $e->setError( Application::ERROR_EXCEPTION )
                ->setParam( 'exception', $exception );
            $eventManager->trigger( MvcEvent::EVENT_DISPATCH_ERROR, $e );
        }
    }

}

这是我的 getServiceConfigMethod

public function getServiceConfig()
{
    return array(
        'factories' => array(
            'Session' => '\My\Mvc\Service\SessionFactory',
            '\Zend\Db\Adapter\Adapter' => '\Zend\Db\Adapter\AdapterServiceFactory'
        )
    );
}

我现在正在使用 sqllite,所以该表必须已经存在于您的 sqllite 文件中。

如果您使用的是 mysql,它也应该存在于该数据库中,您应该更改 application.config.php 文件中的数据库设置。

关于php - Zend Framework 2 - 如何对自己的 session 服务进行单元测试?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14032267/

相关文章:

session - 多个 Grails 项目的单一身份验证

php - 在函数中使用 "use"?

PHP/Gettext 问题

php - 有没有办法告诉 PHPStorm 隐藏方法/函数/变量/等

javascript - Angular,Jasmine 模拟整个模块依赖项 ,"is not available!"错误

unit-testing - 我对现有方法的单元测试是否应该失败?

php - 选择 future 14 天内的日期范围

c# - 多语言测试框架

javascript - 尝试从警报更改为弹出窗口

php - 重定向到 codeigniter 中的另一个 View 后 session 过期