我在对自己的 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/