WARNING: This post was written a long time ago. It exists here as a record and may not reflect my current views or opinions. Also, any code, technologies or examples may be out of date.

Now that I’ve got a little MVC application up and running in Zend Framework 2 (see my previous post) I decided it was time to try and get PHPUnit to play with it. While I don’t think I’m alone in wanting to use ZF2 & PHPUnit together it’s certainly something not many people are talking about.

Here I will show how I bootstrapped PHPUnit with the Zend Framework.

First thing I did was create a tests folder in the root of my project folder:

composer.json
composer.phar
data
module
README.md
vendor
composer.lock
config
init_autoloader.php
public
tests

Next up I created a phpunit.xml configuration inside the tests directory containing the following XML:

<phpunit
    bootstrap="./Bootstrap.php"
    colors="true"
    backupGlobals="false"
>
    <testsuites>
        <testsuite name="Test Suite">
            <directory>;./</directory>
        </testsuite>
    </testsuites>
</phpunit>

Nothing really special in there, the important part is that I’ve told phpunit to use the Bootstrap.php file to get things set up.

So next up I needed to create the Boostrap.php file. I came to the conclusion that I could probably use the same init_autoloader.php file that default/index.php in the ZF2 Skeleton Application uses to get the autoloader up and running.

So I created the following content in the Bootstrap.php:

<?php
 
chdir(dirname(__DIR__));
 
include __DIR__ . '/../init_autoloader.php';

This seemed to do the trick and I could autoload classes from the Zend Framework, however I still couldn’t autoload my classes from my MVC application module.

I knew I some how needed to pull in the MVC configuration from the the application and after stepping through the code a bit I came to the conclusion I needed to add the following code:

$configuration = include 'config/application.config.php';

$serviceManager = new ServiceManager(new ServiceManagerConfiguration($configuration));
$serviceManager->setService('ApplicationConfiguration', $configuration);
$moduleManager = $serviceManager->get('ModuleManager');
$moduleManager->loadModules();

This gets the application config loaded from config/application.config.php and then loads the config for the modules listed in there. So now my whole Bootloader.php looks like this:

<?php

use Zend\ServiceManager\ServiceManager,
    Zend\Mvc\Service\ServiceManagerConfiguration;

chdir(dirname(__DIR__));

include __DIR__ . '/../init_autoloader.php';

$configuration = include 'config/application.config.php';

$serviceManager = new ServiceManager(new ServiceManagerConfiguration($configuration));
$serviceManager->setService('ApplicationConfiguration', $configuration);
$moduleManager = $serviceManager->get('ModuleManager');
$moduleManager->loadModules();

Now my classes in my modules would easily autoload, marvelous!

Update

I have since realised that this setup is down in the init() method of Zend\Mvc\Application therefore the Bootstrap.php file can be reduced down to:

<?php
chdir(dirname(__DIR__));

include __DIR__ . '/../init_autoloader.php';

Zend\Mvc\Application::init(include 'config/application.config.php');

Next up was to write a test. I decided the directory structure in my tests folder would mirror my code tree so I created module/Album/src/Album/Model/ and put a new file in there called AlbumTest.php

I wrote the following test code:

<?php

use Album\Model\Album,
    Zend\InputFilter\InputFilterInterface;

class AlbumTest extends \PHPUnit_Framework_TestCase
{
    protected $a;

    public function setUp()
    {
        $this->a = new Album;
    }

    /**
     * @expectedException Album\Model\AlbumException
     * @expectedExceptionMessage Not used
     */
    public function testSetInputFilter()
    {
        $if = $this->getMock('Zend\InputFilter\InputFilterInterface');
        $this->a->setInputFilter($if);
    }
 
    public function testGetInputFilter()
    {
        $if = $this->a->getInputFilter();
 
        $this->assertInstanceOf("Zend\InputFilter\InputFilter", $if);
        return $if;
    }
 
    /**
     * @depends testGetInputFilter
     */
    public function testInputFilterValid($if)
    {
        $this->assertEquals(3, $if->count());
 
        $this->assertTrue($if->has('title'));
        $this->assertTrue($if->has('artist'));
        $this->assertTrue($if->has('id'));
    }
}

I won’t go into detail about what that test does, that can all be looked up in the PHPUnit documentation. One thing I did do through was make Album::setInputFilter throw AlbumException instead of Exception, the reason for this is PHPUnit 3.6 doesn’t like checking for Exception classes, apparently this is fixed in 3.7.

So anyway, not when I cd into my tests directory and type phpunit I get the following output:

PHPUnit 3.6.11 by Sebastian Bergmann.
Configuration read from /home/tom/workspace/ZF2Tutorial/tests/phpunit.xml
...
Time: 0 seconds, Memory: 5.25Mb
OK (3 tests, 7 assertions)

Success!

Next up, time to work out how to use PHPUnit with classes that access the database and controller classes.