Question

I have an application that is behind a login and utilizes zend_acl and zend_auth.

During pre-dispatch I have an ACL plugin that creates all the rules out for the ACL. I also have an Auth plugin that checks if you're logged in or not and if so if you have access to the requested resource according to the ACL.

As the application is entirely behind a login the ACL is only created if you're logged in.

Unit testing this appears to be impossible, or rather more likely I'm missing something obvious.

In my unit test setup method I simulate a successful login that returns a zend_auth instance. Tests that do pass indicate that this login was successful.

However, if I then through tests attempt to dispatch to another location, or assess if the logged in user has access to a given resource it is always rejected by the plugin as they're still not logged in. I am not sure why this is, can anyone advise?

For example this passes:

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

This fails as it's rejected by the plugin:

 public function testUserAccess()
 {

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

 }

This, I have found still seems to be redirecting back to the login page as the plugins don't know the user is logged in.

Any help much appreciated.

Was it helpful?

Solution

The Problem you describe happens a lot with the usage of global variables and the OOP global variable (the Singleton Pattern).

There is an article by the author of PHPUnit that describes how you can avoid that by using Dependency Injection and what other possibilities you've got and since it's very descriptive, I just suggest you to read it :) http://sebastian-bergmann.de/archives/882-Testing-Code-That-Uses-Singletons.html

As an ugly alternative (if you need a quick result) you could create a stub of Zend_Auth (describe in the link) and use the PHP 5.3 reflection API to set the Zend_Auth instance variable to your stub.

Hope that helps (as the question lived 4h without an other answer)

OTHER TIPS

Here is another way of creating a stub to replace your ACL Plugin (or any plugin) during testing. Put this in your ControllerTestCase and call it in the test case setUp.

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); 
}

This way your stub preDispatch method is called instead, which will bypass your actual access control checks.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top