使用 ZfcUser 的控制器的简单 ZF2 单元测试
我在尝试对使用 ZfcUser 进行身份验证的操作进行单元测试时遇到问题.我需要一些方法来模拟 ZfcUser 控制器插件,但我不太确定如何做到这一点.我已经成功地为表和模型生成了一些单元测试,但是控制器需要大量注入的对象并导致问题.有谁知道如何设置 ZfcUser 模拟以成功对控制器进行单元测试?
I'm having issues trying to unit test an action which uses ZfcUser for authentication. I need some way to mock the ZfcUser Controller plugin but I'm not so sure how to do this. I've managed to successfully produce some unit tests for tables and models but the controller requires a lot of injected objects and is causing problems. Does anyone know how to set up the ZfcUser mocks to successfully unit test a controller?
这是我的测试(复制自 ZF2 教程):
Here is my test (copied from the ZF2 tutorial):
<?php
namespace SmsTestController;
use SmsTestBootstrap;
use SmsControllerSmsController;
use ZendHttpRequest;
use ZendHttpResponse;
use ZendMvcMvcEvent;
use ZendMvcRouterRouteMatch;
use ZendMvcRouterHttpTreeRouteStack as HttpRouter;
use PHPUnit_Framework_TestCase;
class SmsControllerTest extends PHPUnit_Framework_TestCase
{
protected $controller;
protected $request;
protected $response;
protected $routeMatch;
protected $event;
protected function setUp()
{
$serviceManager = Bootstrap::getServiceManager();
$this->controller = new SmsController();
$this->request = new Request();
$this->routeMatch = new RouteMatch(array('controller' => 'index'));
$this->event = new MvcEvent();
$config = $serviceManager->get('Config');
$routerConfig = isset($config['router']) ? $config['router'] : array();
$router = HttpRouter::factory($routerConfig);
$this->event->setRouter($router);
$this->event->setRouteMatch($this->routeMatch);
$this->controller->setEvent($this->event);
$this->controller->setServiceLocator($serviceManager);
}
/* Test all actions can be accessed */
public function testIndexActionCanBeAccessed()
{
$this->routeMatch->setParam('action', 'index');
$result = $this->controller->dispatch($this->request);
$response = $this->controller->getResponse();
$this->assertEquals(200, $response->getStatusCode());
}
}
我在setUp方法中尝试了以下:
I tried the following in the setUp method:
$mockAuth = $this->getMock('ZfcUserEntityUserInterface');
$authMock = $this->getMock('ZendAuthenticationAuthenticationService');
$authMock->expects($this->any())
->method('hasIdentity')
->will($this->returnValue(true));
$authMock->expects($this->any())
->method('getIdentity')
->will($this->returnValue(array('user_id' => 1)));
但我不确定如何将它注入到控制器实例中.
But I'm not sure how to inject this in to the controller instance.
假设我的索引操作代码如下:
Lets pretend my index action code is just as follows:
public function indexAction() {
//Check if logged in
if (!$this->zfcUserAuthentication()->hasIdentity()) {
return $this->redirect()->toRoute('zfcuser/login');
}
return new ViewModel(array(
'success' => true,
));
}
测试结果:
1) SmsTestControllerSmsControllerTest::testIndexActionCanBeAccessed
ZendServiceManagerExceptionServiceNotFoundException: ZendServiceManagerServiceManager::get was unable to fetch or create an instance for zfcUserAuthentication
/var/www/soap-app.localhost/Zend/vendor/zendframework/zendframework/library/Zend/ServiceManager/ServiceManager.php:450
/var/www/soap-app.localhost/Zend/vendor/zendframework/zendframework/library/Zend/ServiceManager/AbstractPluginManager.php:110
/var/www/soap-app.localhost/Zend/vendor/zendframework/zendframework/library/Zend/Mvc/Controller/PluginManager.php:90
/var/www/soap-app.localhost/Zend/vendor/zendframework/zendframework/library/Zend/Mvc/Controller/AbstractController.php:276
/var/www/soap-app.localhost/Zend/vendor/zendframework/zendframework/library/Zend/Mvc/Controller/AbstractController.php:291
/var/www/soap-app.localhost/Zend/module/Sms/src/Sms/Controller/SmsController.php:974
/var/www/soap-app.localhost/Zend/module/Sms/src/Sms/Controller/SmsController.php:974
/var/www/soap-app.localhost/Zend/module/Sms/src/Sms/Controller/SmsController.php:158
/var/www/soap-app.localhost/Zend/vendor/zendframework/zendframework/library/Zend/Mvc/Controller/AbstractActionController.php:87
/var/www/soap-app.localhost/Zend/vendor/zendframework/zendframework/library/Zend/EventManager/EventManager.php:468
/var/www/soap-app.localhost/Zend/vendor/zendframework/zendframework/library/Zend/EventManager/EventManager.php:208
/var/www/soap-app.localhost/Zend/vendor/zendframework/zendframework/library/Zend/Mvc/Controller/AbstractController.php:108
/var/www/soap-app.localhost/Zend/module/Sms/test/SmsTest/Controller/SmsControllerTest.php:57
导致此异常的行是控制器: if (!$this->zfcUserAuthentication()->hasIdentity()) {
该行与 SmsController 中的第 974 行相关.
The line which causes this exception is the controller is: if (!$this->zfcUserAuthentication()->hasIdentity()) {
That line relates to line 974 in the SmsController.
很明显我无权访问 ZfcUserAuthentication 服务,所以问题是,如何模拟 ZfcUserAuthentication 服务并将其注入到我的 Controller 中?
It's obvious I don't have access to the ZfcUserAuthentication service, so the question is, How do I mock the ZfcUserAuthentication service and inject it in to my Controller?
要继续主题,我将如何模拟登录用户以成功测试我的操作是否符合规范?
To continue the theme how would I go about mocking a logged in user to successfully test my action is working to specification?
推荐答案
ZfcUser 文档表明这是一个插件,因此您需要将其注入到控制器中.
The ZfcUser documentation suggests that this is a plugin so you need to inject this into the controller.
你需要修改你的类名来选择 ZfcUser 类
You will need to amend your class names to pick up the ZfcUser classes
您的模拟也需要添加,因为 getIdenty 返回不同的对象.
Your mocks will also need to be addapted as getIdenty returns a different object.
以下内容对我有用 - 插入您的 phpunit setUp() 方法.
The following worked for me - insert in your phpunit setUp() method.
$serviceManager = Bootstrap::getServiceManager();
$this->controller = new RegisterController();
$this->request = new Request();
$this->routeMatch = new RouteMatch(array('controller' => 'add'));
$this->event = new MvcEvent();
$config = $serviceManager->get('Config');
$routerConfig = isset($config['router']) ? $config['router'] : array();
$router = HttpRouter::factory($routerConfig);
$this->event->setRouter($router);
$this->event->setRouteMatch($this->routeMatch);
$this->controller->setEvent($this->event);
$this->controller->setServiceLocator($serviceManager);
$mockAuth = $this->getMock('ZfcUserEntityUserInterface');
$ZfcUserMock = $this->getMock('ZfcUserEntityUser');
$ZfcUserMock->expects($this->any())
->method('getId')
->will($this->returnValue('1'));
$authMock = $this->getMock('ZfcUserControllerPluginfcUserAuthentication');
$authMock->expects($this->any())
->method('hasIdentity')
-> will($this->returnValue(true));
$authMock->expects($this->any())
->method('getIdentity')
->will($this->returnValue($ZfcUserMock));
$this->controller->getPluginManager()
->setService('zfcUserAuthentication', $authMock);
可能有一种更简单的方法会欢迎其他想法.
There may be an easier way would welcome other thoughts.
相关文章