使用ZfcUser对控制器进行简单的ZF2单元测试 [英] Simple ZF2 Unit Tests for a controller using ZfcUser

查看:71
本文介绍了使用ZfcUser对控制器进行简单的ZF2单元测试的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在尝试对使用ZfcUser进行身份验证的操作进行单元测试时遇到问题.我需要某种方法来模拟ZfcUser Controller插件,但是我不确定如何执行此操作.我已经成功地为表格和模型制作了一些单元测试,但是控制器需要大量注入的对象,并且会引起问题.有谁知道如何设置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 SmsTest\Controller;

use SmsTest\Bootstrap;
use Sms\Controller\SmsController;
use Zend\Http\Request;
use Zend\Http\Response;
use Zend\Mvc\MvcEvent;
use Zend\Mvc\Router\RouteMatch;
use Zend\Mvc\Router\Http\TreeRouteStack 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('ZfcUser\Entity\UserInterface');


    $authMock = $this->getMock('Zend\Authentication\AuthenticationService');
    $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) SmsTest\Controller\SmsControllerTest::testIndexActionCanBeAccessed
Zend\ServiceManager\Exception\ServiceNotFoundException: Zend\ServiceManager\ServiceManager::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('ZfcUser\Entity\UserInterface');

$ZfcUserMock = $this->getMock('ZfcUser\Entity\User');  

$ZfcUserMock->expects($this->any())
            ->method('getId')
            ->will($this->returnValue('1'));

$authMock = $this->getMock('ZfcUser\Controller\Plugin\ZfcUserAuthentication');

$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.

这篇关于使用ZfcUser对控制器进行简单的ZF2单元测试的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆