1
votes

I'm unit testing a ZF2 Controller, below is the test class:

<?php
class RestControllerTest extends AbstractHttpControllerTestCase
{
    public function setUp()
    {
        Bootstrap::init();
        $this->setApplicationConfig(Bootstrap::getConfig());
        parent::setup();
    }

    public function testCreate()
    {
        $paramsArr = array(/** Params Here **/);
        $this->dispatch('/transcode', 'POST', $paramsArr);
        $this->assertResponseStatusCode(204);
        $this->assertControllerName('Transcode\Controller\Rest');
        $this->assertMatchedRouteName('transcode');
    }
}

My unit test is failing, indicating a ServiceNotFoundException on logger.transcode, which is attached to the eventmanager onBootstrap of the Transcode module:

public function onBootstrap(MvcEvent $e)
    {
        $eventManager   = $e->getApplication()->getEventManager();
        $app            = $e->getTarget();
        $serviceManager = $app->getServiceManager();
        $eventManager->attach($serviceManager->get('Transcode\Listener'));
    }

Transcode\Listener is instantiated via a Factory:

public function createService(ServiceLocatorInterface $serviceLocator)
{
    $logger = $serviceLocator->get('logger.transcode');
    $service = new TranscodeListener($logger);
    return $service;
}

And finally, logger.transcode is set via a config file which creates logger.transcode as an abstract factory in the EnliteMonolog module.

Any idea why the unit test can't attach the listener to workflow?

Per request in the comments, the Bootstrap file is below, although it's a standard ZF2 Test Bootstrap file:

<?php

namespace TranscodeTest;

use Zend\Loader\AutoloaderFactory;
use Zend\Mvc\Service\ServiceManagerConfig;
use Zend\ServiceManager\ServiceManager;
use Zend\Stdlib\ArrayUtils;
use RuntimeException;
use Dotenv;

error_reporting(E_ALL | E_STRICT);
chdir(__DIR__);

class Bootstrap
{
    protected static $serviceManager;
    protected static $config;
    protected static $bootstrap;

    public static function init()
    {
        // Load the user-defined test configuration file, if it exists; otherwise, load
        if (is_readable(__DIR__ . '/TestConfiguration.php')) {
            $testConfig = include __DIR__ . '/TestConfiguration.php';
        }

        $zf2ModulePaths = array();

        if (isset($testConfig['module_listener_options']['module_paths'])) {
            $modulePaths = $testConfig['module_listener_options']['module_paths'];
            foreach ($modulePaths as $modulePath) {
                if (($path = static::findParentPath($modulePath)) ) {
                    $zf2ModulePaths[] = $path;
                }
            }
        }

        $zf2ModulePaths  = implode(PATH_SEPARATOR, $zf2ModulePaths) . PATH_SEPARATOR;
        $zf2ModulePaths .= getenv('ZF2_MODULES_TEST_PATHS') ?: (defined('ZF2_MODULES_TEST_PATHS') ? ZF2_MODULES_TEST_PATHS : '');

        static::initAutoloader();

        // use ModuleManager to load this module and it's dependencies
        $baseConfig = array(
            'module_listener_options' => array(
                'module_paths' => explode(PATH_SEPARATOR, $zf2ModulePaths),
            ),
        );

        $config = ArrayUtils::merge($baseConfig, $testConfig);

        $serviceManager = new ServiceManager(new ServiceManagerConfig());
        $serviceManager->setService('ApplicationConfig', $config);
        $serviceManager->get('ModuleManager')->loadModules();

        static::$serviceManager = $serviceManager;
        static::$config = $config;
    }

    public static function getServiceManager()
    {
        return static::$serviceManager;
    }

    public static function getConfig()
    {
        return static::$config;
    }

    protected static function initAutoloader()
    {
        $vendorPath = static::findParentPath('vendor');

        if (is_readable($vendorPath . '/autoload.php')) {
            $loader = include $vendorPath . '/autoload.php';
        } else {
            $zf2Path = getenv('ZF2_PATH') ?: (defined('ZF2_PATH') ? ZF2_PATH : (is_dir($vendorPath . '/ZF2/library') ? $vendorPath . '/ZF2/library' : false));

            if (!$zf2Path) {
                throw new RuntimeException('Unable to load ZF2. Run `php composer.phar install` or define a ZF2_PATH environment variable.');
            }

            include $zf2Path . '/Zend/Loader/AutoloaderFactory.php';

        }

        AutoloaderFactory::factory(array(
            'Zend\Loader\StandardAutoloader' => array(
                'autoregister_zf' => true,
                'namespaces' => array(
                    __NAMESPACE__ => __DIR__ . '/' . __NAMESPACE__,
                ),
            ),
        ));

        if (getenv('APPLICATION_ENV') != 'PRODUCTION') {
            Dotenv::load('../../../config');
        }
    }

    protected static function findParentPath($path)
    {
        $dir = __DIR__;
        $previousDir = '.';
        while (!is_dir($dir . '/' . $path)) {
            $dir = dirname($dir);
            if ($previousDir === $dir) return false;
            $previousDir = $dir;
        }
        return $dir . '/' . $path;
    }
}

Bootstrap::init();
1
Can we see the test Bootstrap?Tim Klever
How incredibly embarrassing..... it seems I forgot to add the EnliteMonolog to the TestConfiguration file. Once that was added, the test ran as expected. It seems that sometimes you stare at code a little too long.....R Down

1 Answers

0
votes

Embarrassingly, it seems I forgot to add the 'EnliteMonolog' to the TestConfiguration.php file. Once I added that module the test ran as expected. It seems you can, in fact look at code for too long

<?php
return array(
'modules' => array(
    'Transcode',
    /** Other modules needed **/
    'EnliteMonolog',
),
'module_listener_options' => array(
    'config_glob_paths'    => array(
        '../../../config/autoload/{,*.}{global,local}.php',
    ),
    'module_paths' => array(
        'module',
        'vendor',
    ),
),);