Phpunit ZF2单元测试认证

Phpunit ZF2单元测试认证,phpunit,zend-framework2,zfcuser,Phpunit,Zend Framework2,Zfcuser,我正在学习单元测试,并试图解决以下问题: Zend\ServiceManager\ServiceManager::get was unable to fetch or create an instance for zfcUserAuthentication 。。。使用以下给出的唯一答案: 所以我的设置函数看起来是一样的。不幸的是,我收到了错误消息: Zend\Mvc\Exception\InvalidPluginException: Plugin of type Mock_ZfcUserAu

我正在学习单元测试,并试图解决以下问题:

Zend\ServiceManager\ServiceManager::get was unable to fetch or create an instance for zfcUserAuthentication
。。。使用以下给出的唯一答案:

所以我的设置函数看起来是一样的。不幸的是,我收到了错误消息:

Zend\Mvc\Exception\InvalidPluginException: Plugin of type Mock_ZfcUserAuthentication_868bf824 is invalid; must implement Zend\Mvc\Controller\Plugin\PluginInterface
这是由代码的这一部分引起的(在我的代码中以相同的方式拆分):

$authMock对象显然没有实现plugininterface,我需要实现它才能传递到setService

$authMock不是为了在单元测试中使用而通过的吗?我应该使用不同的(面向单元测试的)setService方法吗

我需要一种方法来处理登录到我的应用程序,否则我的单元测试就没有意义了

谢谢你的建议

==编辑(11/02/2013)===

我想集中在这一部分进行澄清,因为我认为这是问题所在:

// Getting mock of authentication object, which is used as a plugin.
$authMock = $this->getMock('ZfcUser\Controller\Plugin\ZfcUserAuthentication');

// Some expectations of the authentication service.
$authMock   -> expects($this->any())
    -> method('hasIdentity')
    -> will($this->returnValue(true));  

$authMock   -> expects($this->any())
    -> method('getIdentity')
    -> will($this->returnValue($ZfcUserMock));

// At this point, PluginManager disallows mock being assigned as plugin because 
// it will not implement plugin interface, as mentioned.
$this -> controller->getPluginManager()
->setService('zfcUserAuthentication', $authMock);

如果mock没有处理必要的实现,我怎么能假装登录呢?

您的名字间隔或自动加载器有问题

创建模拟时,找不到
ZfcUser\Controller\Plugin\ZfcUserAuthentication
的类定义。所以PHPUnit创建了一个mock,该mock只扩展这个类用于测试。如果该类可用,那么PHPUnit将在创建其mock时使用实际类进行扩展,然后使用父类/接口

您可以在这里看到这种逻辑:

因此,如果没有类或接口,PHPUnit实际上会自己创建一个类或接口,以便mock满足原始类名的类型暗示。但是,不会包括任何父类或接口,因为PHPUnit不知道它们

这可能是因为测试中没有包含正确的名称空间,或者自动加载程序有问题。如果看不到整个测试文件,就很难判断


或者,您可以在测试中模拟
Zend\Mvc\Controller\Plugin\PluginInterface
,而不是模拟
ZfcUser\Controller\Plugin\ZfcUserAuthentication
,并将其传递到插件管理器。虽然如果您在代码中为插件输入提示,您的测试仍然无法工作

//Mock the plugin interface for checking authorization
$authMock = $this->getMock('Zend\Mvc\Controller\Plugin\PluginInterface');

// Some expectations of the authentication service.
$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);

我刚刚为FlashMessenger插件做了一个示例。您应该只使用ControllerPluginManager来覆盖ControllerPlugin。确保应用程序引导调用setApplicationConfig()



我说得对吗?没有必要像模型那样对控制器进行单元测试吗?我发现这就是我保存所有身份验证代码的地方。我最近做了类似的事情,没有任何问题。您的整个testcase类是什么样子的?您的测试引导程序是什么样子的?最后是您尝试测试的操作。单元测试时是否使用特殊的应用程序配置?在这种情况下,测试环境中可能未加载zfcUser模块。
    if (!class_exists($mockClassName['fullClassName'], $callAutoload) &&
        !interface_exists($mockClassName['fullClassName'], $callAutoload)) {
        $prologue = 'class ' . $mockClassName['originalClassName'] . "\n{\n}\n\n";

        if (!empty($mockClassName['namespaceName'])) {
            $prologue = 'namespace ' . $mockClassName['namespaceName'] .
                        " {\n\n" . $prologue . "}\n\n" .
                        "namespace {\n\n";

            $epilogue = "\n\n}";
        }

        $cloneTemplate = new Text_Template(
          $templateDir . 'mocked_clone.tpl'
        );
//Mock the plugin interface for checking authorization
$authMock = $this->getMock('Zend\Mvc\Controller\Plugin\PluginInterface');

// Some expectations of the authentication service.
$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);
<?php
namespace SimpleTest\Controller;

use Zend\Test\PHPUnit\Controller\AbstractHttpControllerTestCase;

class SimpleControllerTest extends AbstractHttpControllerTestCase {

  public function testControllerWillAddErrorMessageToFlashMessenger()
  {
      $flashMessengerMock = $this->getMockBuilder('\Zend\Mvc\Controller\Plugin\FlashMessenger', array('addErrorMessage'))->getMock();
      $flashMessengerMock->expects($this->once())
          ->method('addErrorMessage')
          ->will($this->returnValue(array()));


      $serviceManager = $this->getApplicationServiceLocator();
      $serviceManager->setAllowOverride(true);
      $serviceManager->get('ControllerPluginManager')->setService('flashMessenger', $flashMessengerMock);

      $this->dispatch('/error/message');

  }
}?>