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.

Yesterday, I was trying to test that the ServiceManager was correctly creating an instance of a class which took a Zend\Http\Request object as a parameter to the constructor. The problem I ran into was that since the Zend MVC Application had been initialised from PHPUnit, it decided it was running in a console context and was using a Zend\Console\Request instead.

After a bit of hunting around I came up with the following, simple solution:

<?php

class MyModuleTest extends \PHPUnit_Framework_TestCase
{
    /**
     * The test which requires a HTTP Request object.
     */
    public function test_service_manager_creates_successfully()
    {
        $serviceManager = \TestBootstrap::getApplication()
                                    ->getServiceManager();

        $this->setRequestTypeToHttp();

        $this->assertInstanceOf(
            'MyModule\ClassBeingTested',
            $serviceManager->get('MyModule\ClassBeingTested')
        );
    }

    /**
     * Sets the service manager to return an instance of \Zend\Http\Request
     * instead of its default.
     */
    private function setRequestTypeToHttp($serviceManager)
    {
        // This needs to be set so we can change the service manager config
        $serviceManager->setAllowOverride(true);

        // Replace the Request service with a callback which creates
        // a \Zend\Http\Request instance instead
        $serviceManager->setFactory('Request', function ($sm) {
            return new \Zend\Http\Request();
        });
    }
}

My PHPUnit boostrap file for reference

<?php

class TestBootstrap
{
    private static $autoloaderFiles = [
        '../vendor/autoload.php',
    ];

    private static $application;

    /**
     * Setup the testing environment.
     *
     * @param  string $config Path to the Zend application config file.
     * @return void
     */
    public static function init($config)
    {
        $loader = self::getAutoloader();

        //$loader->add('ModuleTestNamespace\\', __DIR__);

        self::$application = \Zend\Mvc\Application::init($config);
    }

    /**
     * Return the application instance.
     *
     * @return \Zend\Mvc\Application
     */
    public static function getApplication()
    {
        return self::$application;
    }

    private static function getAutoloader()
    {
        global $loader;

        foreach (self::$autoloaderFiles as $file) {
            if ($file[1] !== '/') {
                $file = __DIR__ . '/' . $file;
            }


            if (file_exists($file)) {
                $loader = include $file;
                break;
            }
        }

        if (!isset($loader) || !$loader) {
            throw new \RuntimeException('vendor/autoload.php not found. Have you run composer?');
        }

        return $loader;
    }
}

TestBootstrap::init(include __DIR__ . '/application.config.php');