Over a million developers have joined DZone.

Unit testing controller actions with Zend_Test_PHPUnit_ControllerTestCase

DZone's Guide to

Unit testing controller actions with Zend_Test_PHPUnit_ControllerTestCase

· Web Dev Zone
Free Resource

Learn how to build modern digital experience apps with Crafter CMS. Download this eBook now. Brought to you in partnership with Crafter Software

Testing controllers has traditionally been a hassle due to the requirements of setting up the bootstrap, the front controller and initiating the dispatch cycle. In June, Matthew addressed this with the release of Zend_Test_PHPUnit_ControllerTestCase way back in 2008.

Later, Matthew helpfully wrote an article on how to use it and I have used that as a starting point for the information here. (Thanks Matthew!)

The project I'm using is TodoIt, which is a simple ZF demo application, which needs unit tests.

Setting up PHPUnit

All your unit tests will live in the /tests folder. The ZF cli tool will create a phpunit.xml file for you, but you'll discover that it's empty! This is what it should look like:

<phpunit colors="true" bootstrap="./TestHelper.php">
<testsuite name="TodoIt Test Suite">

<directory suffix=".php">../library/</directory>
<directory suffix=".php">../application/</directory>
<directory suffix=".phtml">../application/</directory>

<log highlowerbound="80" lowupperbound="50" highlight="true" yui="true" charset="UTF-8" target="./log/report" type="coverage-html"></log>



This file is used to configure phpunit itself and saves having to use command line options. As it's XML, it's fairly easy to read. The testsuites element is used to specify the testsuite we're going to test. In principle you can have many test suites; in this case, one is enough! The filter section is used to specify which files to use for code coverage reporting and the logging section is used to configure the reports.

We also specify TestHelper.php as the bootstrap. This mean that it is called for us and contains the necessary PHP setup we need to do in order to load and use Zend Framework. In effect TestHelper.php acts like public/index.php does for your web application. TestHelper.php looks like this:

// Based on http://weierophinney.net/matthew/archives/190-Setting-up-your-Zend_Test-test-suites.html

// PHP settings
error_reporting(E_ALL | E_STRICT);

define('APPLICATION_ENV', 'unittesting');
define('APPLICATION_PATH', realpath(dirname(__FILE__) . '/../application'));

// Directories for include path
$root = realpath(dirname(__FILE__) . '/../');
$library = $root . '/library';
$models = $root . '/application/models';

$path = array(
set_include_path(implode(PATH_SEPARATOR, $path));

require_once 'Zend/Loader/Autoloader.php';

// Unset global variables
unset($root, $library, $models, $path);

As with public/index.php, we set APPLICATION_ENV and APPLICATION_PATH, update the include_path and then set up the autoloader. Now we're all ready to write some tests!

A controller test class

I place my controller test classes in tests/application/controllers to make them easy to find. (Model tests go in tests/application/models!). The TodoIt application has a login form in AuthController::indexAction() which is accessed via the /auth URL. We'll start by testing this form is displayed.

The controller's test class is called AuthControllerTest and lives in tests/application/controllers/AuthControllerTest.php:


// Call AuthControllerTest::main() if this source file is executed directly.
if (!defined("PHPUnit_MAIN_METHOD")) {
define("PHPUnit_MAIN_METHOD", "AuthControllerTest::main");

require_once 'PHPUnit/Framework/TestCase.php';

* @group Controllers
class AuthControllerTest extends Zend_Test_PHPUnit_ControllerTestCase
public static function main()
$suite = new PHPUnit_Framework_TestSuite(get_class($this));
$result = PHPUnit_TextUI_TestRunner::run($suite);

public function setUp()
$application = new Zend_Application(
APPLICATION_PATH . '/configs/application.ini'

$this->bootstrap = $application;
return parent::setUp();

public function tearDown()
/* Tear Down Routine */

public function testLoginDisplaysAForm()
$this->assertQueryContentContains('h1', 'Login');
$this->assertQuery('form#login'); // id of form


There's three things going on in here, so let's look at each in turn.

Firstly we set up the file to allow PHPUnit to run this file on it's own using the command line:

phpunit tests\application\controllers\AuthControllerTest.php

This is done by setting the PHPUnit_MAIN_METHOD constant to the static method AuthControllerTest::main(). The phpunit cli tool will then run this method which will in turn run this file as a test suite.

The methods setUp() and tearDown() are called before and after every test method and are used to ensure that we have a clean slate for each one. As we extended from Zend_Test_PHPUnit_ControllerTestCase rather than from PHPUnit_Framework_TestCase, we are able to leverage functionality specifically designed to make testing controllers easier. We use this in setUp() to set the property bootstrap to an instance of Zend_Application, which is then used in the tests themselves.

Each test is a method that starts with the word test, like this one:

    public function testLoginDisplaysAForm()
$this->assertQueryContentContains('h1', 'Login');
$this->assertQuery('form#login'); // id of form

We start by calling dispatch() to run the correct action and then we use the various assert methods to check that the result is what we expect. The assertResponseCode method checks that we didn't error as the errorController will set the code to 500 or 404. We can then use the assertQuery methods to check what has been rendered to the response object. These use DOM paths to select a specific element. The call to assertQueryContentContains allows us to check the text within the H1 element is what we expect and the assertQuery just checks that the element is on the page.

That's it.

This is just the tip of the iceberg and I strongly suggest that you have a read of the documentation to see for yourself how many different assertions you can use to check that your code is performing as expected.




Crafter is a modern CMS platform for building modern websites and content-rich digital experiences. Download this eBook now. Brought to you in partnership with Crafter Software.


Published at DZone with permission of Rob Allen, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.


Dev Resources & Solutions Straight to Your Inbox

Thanks for subscribing!

Awesome! Check your inbox to verify your email so you can start receiving the latest in tech news and resources.


{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}