Setting up a Controller Test with ZendFramework: Autoloader issue

875 views Asked by At

I'm working on a web application with Zend Framework v1.11.0, but I'm failing to set up a correct test environment for controller tests. I know that there are already a lot of questions about setting up Zend test, however, after hours of research, none of these fixed my problem. So here is my code:

Test Bootstrap:

<?php
error_reporting(E_ALL | E_STRICT);

defined('APPLICATION_PATH') || define('APPLICATION_PATH',realpath(dirname(__FILE__).'/../../application'));
define('APPLICATION_ENV', 'testing');
set_include_path(implode(PATH_SEPARATOR, array(realpath(APPLICATION_PATH.'/../library'), get_include_path())));

require_once ('Zend/Application.php');
require_once ('ControllerTestCase.php');

ControllerTestCase:

class ControllerTestCase extends Zend_Test_PHPUnit_ControllerTestCase {

  public $application;

  public function setUp() {
    $this->bootstrap = array($this, 'appBootstrap');
    parent::setUp();
  }

  public function appBootstrap() {
    $this->application = new Zend_Application(APPLICATION_ENV, APPLICATION_PATH.'/configs/application.ini');
    $this->application->bootstrap();
  }
}

Simple Test:

class IndexControllerTest extends ControllerTestCase {
    public function testDefaultShouldInvokeIndexAction()
    {
        $this->dispatch('/');
        $this->assertModule('default');
        $this->assertController('index');
        $this->assertAction('index');
    }
}

Everytime I run this test, PHPUnit throws a fatal error message not finding a class in my library that is used in my IndexController. Therefore the reason must be something related to the Autoloader, I thought. After debugging I found out, that the test runs through the regular Bootstrap, trough the Auth plugin and so on and that my libraries are included. So I have no idea what PHPUnit's problem might be. In browser everything works fine and non-controller tests in the commandline (e.g. global settings) work, too.

I'd be very grateful for any hint what i need to do to get my controller tests working!

edit: my directory structure looks like this (I separated my classes into different libraries for certain reasons)

project
 - library1
 - library2
 - project_name
    ->application
    ->library3
    ->library4
    ->tests
       ->>application
          ->>>ControllerTestCase.php
          ->>>Bootstrap.php
       ->>Controller
          ->>>IndexControllerTest.php

my include paths look actually like:

set_include_path(implode(PATH_SEPARATOR, array(realpath(APPLICATION_PATH.'/../library3'), get_include_path())));
set_include_path(implode(PATH_SEPARATOR, array(realpath(APPLICATION_PATH.'/../library4'), get_include_path())));
set_include_path(implode(PATH_SEPARATOR, array(realpath(APPLICATION_PATH.'/../../library1'), get_include_path())));
set_include_path(implode(PATH_SEPARATOR, array(realpath(APPLICATION_PATH.'/../../library2'), get_include_path())));
2

There are 2 answers

4
Jan-Henk On

In my own ControllerTestCase class I set the bootstrap object in the constructor instead of the setUp function. So for you that would mean to change this

public function setUp() {
    $this->bootstrap = array($this, 'appBootstrap');
    parent::setUp();
}

into

public function __construct()
{
    $this->bootstrap = new Zend_Application(
        APPLICATION_ENV,
        APPLICATION_PATH . '/configs/application.ini'
    );
}

and removing the appBootstrap method. That's really the only difference I see between your code and my own code. I that does not fix the problem, it's likely your path settings are off.

0
Sve On

The easiest way to have properly set up test case for Zend Controller is to use the zf tool. By creating your controllers with it, you get automatically generated test cases for them.

zf create controller name index-action-included[=1] module

It creates the following bootstrap:

    defined('APPLICATION_PATH')
    || define('APPLICATION_PATH', realpath(dirname(__FILE__) . '/../application'));

defined('APPLICATION_ENV')
    || define('APPLICATION_ENV', (getenv('APPLICATION_ENV') ? getenv('APPLICATION_ENV') : 'testing'));

set_include_path(implode(PATH_SEPARATOR, array(
    realpath(APPLICATION_PATH . '/../library'),
    get_include_path(),
)));

require_once 'Zend/Loader/Autoloader.php';

...and the controllerTestCase:

class IndexControllerTest extends Zend_Test_PHPUnit_ControllerTestCase
{

    public function setUp()
    {
        $this->bootstrap = new Zend_Application(APPLICATION_ENV, APPLICATION_PATH . '/configs/application.ini');
        parent::setUp();
    }

    ....tests.........
}

You have to add the include paths in the bootstrap and register any custom test autoloaders with spl_autoloader. Also, remember to start phpunit with -c test/phpunit.xml