10

我有一个在登录后使用 zend_acl 和 zend_auth 的应用程序。

在预调度期间,我有一个 ACL 插件,可以为 ACL 创建所有规则。我还有一个 Auth 插件,用于检查您是否已登录,如果已登录,您是否可以根据 ACL 访问所请求的资源。

由于应用程序完全在登录之后,因此只有在您登录时才会创建 ACL。

单元测试这似乎是不可能的,或者更可能我错过了一些明显的东西。

在我的单元测试设置方法中,我模拟了返回 zend_auth 实例的成功登录。确实通过的测试表明此登录成功。

但是,如果我随后通过测试尝试分派到另一个位置,或评估登录用户是否有权访问给定资源,则插件始终拒绝它,因为他们仍未登录。我不确定这是为什么,有人可以建议吗?

例如,这通过:

 public function testLoggedIn()
 {
  $this->assertTrue( Zend_Auth::getInstance()->hasIdentity() );
 }

这失败了,因为它被插件拒绝了:

 public function testUserAccess()
 {

   $this->dispatch('/home');
          $this->assertResponseCode(200);
          $this->assertQueryContentContains('#nav_side');  
          $this->resetRequest()
           ->resetResponse();

 }

我发现这似乎仍然重定向回登录页面,因为插件不知道用户已登录。

非常感谢任何帮助。

4

2 回答 2

4

这是在测试期间创建存根以替换 ACL 插件(或任何插件)的另一种方法。将其放入您的 ControllerTestCase 并在测试用例设置中调用它。

public function doLogin ()
{
    // create a fake identity
    $identity = new stdClass();
    $identity->Username = 'PHPUnit';
    Zend_Auth::getInstance()->getStorage()->write($identity);

    // remove the autoloaded plugin
    $front = Zend_Controller_Front::getInstance();
    $front->unregisterPlugin('My_Controller_Plugin_Acl');

    // create the stub for the Acl class
    $mockaAcl = $this->getMock(
      'My_Controller_Plugin_Acl',
      array('preDispatch'),
      array(),
      'My_Controller_Plugin_AclMock'
    ); 

    // register the stub acl plugin in its place
    $front->registerPlugin($mockAcl); 
}

这样,您的存根 preDispatch 方法将被调用,这将绕过您的实际访问控制检查。

于 2012-01-30T10:01:36.520 回答
3

您描述的问题在使用全局变量和 OOP 全局变量(单例模式)时经常发生。

PHPUnit 的作者有一篇文章描述了如何通过使用依赖注入来避免这种情况以及您拥有的其他可能性,因为它非常具有描述性,我只是建议您阅读它:) http://sebastian-bergmann .de/archives/882-Testing-Code-That-Uses-Singletons.html

作为一个丑陋的替代方案(如果您需要快速结果),您可以创建 Zend_Auth 的存根(在链接中描述)并使用 PHP 5.3 反射 API 将 Zend_Auth 实例变量设置为您的存根。

希望有帮助(因为这个问题在没有其他答案的情况下持续了 4 小时)

于 2010-07-28T16:00:00.103 回答