2012-09-14 9 views
9

Aquí está mi situación. Estoy desarrollando una aplicación Zend Framework 2. Estoy usando el módulo Doctrine para comunicarme con una base de datos MySQL. Está funcionando bien en la aplicación, puedo cargar el administrador de entidades desde el localizador de servicios dentro de mis controladores.Módulo Zend Framework 2 Doctrine 2 - No hay un localizador de servicio en las pruebas de la unidad controladora

Pero dentro de mis pruebas de unidad de controlador, el localizador de servicio no existe y por lo tanto todas las pruebas que se ocupan de la base de datos no están cumpliendo con el mensaje de error como este:

Fatal error: Call to a member function get() on a non-object in /Users/richardknop/Projects/myproject/module/Api/src/Api/Controller/UserController.php on line 19

que han reducido el problema a este método :

$this->getServiceLocator() 

Que funciona en mis controladores pero devuelve NULL en pruebas unitarias.

Ésta es mi application.config.php:

<?php 

return array(
    'modules' => array(
     'DoctrineModule', 
     'DoctrineORMModule', 
     'Api', 
    ), 
    'module_listener_options' => array(
     'config_glob_paths' => array(
      'config/autoload/{,*.}{global,local}.php', 
     ), 
     'module_paths' => array(
      './module', 
      './vendor', 
     ), 
    ), 
); 

Mi archivo local.php con detalles de la conexión de base de datos:

<?php 

return array(
    'doctrine' => array(
     'connection' => array(
      'orm_default' => array(
       'driverClass' => 'Doctrine\DBAL\Driver\PDOMySql\Driver', 
       'params' => array(
        'host'  => 'localhost', 
        'port'  => '3306', 
        'user'  => 'root', 
        'password' => 'root', 
        'dbname' => 'mydb', 
       ), 
      ), 
     ), 
    ), 
); 

En mi module.config.php tengo:

'doctrine' => array(
    'driver' => array(
     __NAMESPACE__ . '_driver' => array(
      'class' => 'Doctrine\ORM\Mapping\Driver\AnnotationDriver', 
      'cache' => 'array', 
      'paths' => array(__DIR__ . '/../src/' . __NAMESPACE__ . '/Entity') 
     ), 
     'orm_default' => array(
      'drivers' => array(
       __NAMESPACE__ . '\Entity' => __NAMESPACE__ . '_driver' 
      ), 
     ), 
    ), 
), 

Y en mis controladores tengo este método para obtener el administrador de la entidad:

private $_em; 

private function _getEntityManager() 
{ 
    if (null === $this->_em) { 
     $this->_em = $this->getServiceLocator()->get('doctrine.entitymanager.orm_default'); 
    } 
    return $this->_em; 
} 

Ahora mis pruebas de la unidad. Aquí está el archivo de arranque:

<?php 

chdir(dirname(__DIR__)); 
include __DIR__ . '/../init_autoloader.php'; 
return Zend\Mvc\Application::init(include 'config/application.config.php'); 

Y método de configuración de mis pruebas controlador se parece a:

public function setUp() 
{ 
    $this->_controller = new UserTokenController; 
    $this->_request = new Request; 
    $this->_routeMatch = new RouteMatch(array('controller' => 'user')); 
    $this->_event = new MvcEvent(); 
    $this->_event->setRouteMatch($this->_routeMatch); 
    $this->_controller->setEvent($this->_event); 
} 

Un ejemplo de prueba de unidad controladora a continuación, se ve así:

public function testGetListHttpStatusCode() 
{ 
    $response = $this->_controller->dispatch($this->_request); 
    $this->assertEquals(405, $response->getStatusCode()); 
} 

Todas las pruebas que sean no se está conectando a la base de datos. Pruebas en las que estoy usando el administrador de entidades están fallando aunque con este error:

Fatal error: Call to a member function get() on a non-object in /Users/richardknop/Projects/myproject/module/Api/src/Api/Controller/UserController.php on line 19

Ésta es la línea 19:

$this->_em = $this->getServiceLocator()->get('doctrine.entitymanager.orm_default'); 

Y la razón por la que está fallando es que $this->getServiceLocator() vuelve NULL.

¿Alguna idea de cómo solucionar este problema?

Respuesta

6

'No hacer esto ins su Bootstrap.php

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

pero algo como esto:

chdir('/path/to/application/root'); 

// if you're using composer to install zf2 
include_once 'vendor/autoload.php'; 
// if not using composer initialize your custom autoloading here 

$configuration = include('config/application.config.php'); 
$serviceManager = new ServiceManager(new ServiceManagerConfig(
    isset($configuration['service_manager']) ? $configuration['service_manager'] : array() 
)); 
$serviceManager->setService('ApplicationConfig', $configuration); 
$serviceManager->setFactory('ServiceListener', 'Zend\Mvc\Service\ServiceListenerFactory'); 

$moduleManager = $serviceManager->get('ModuleManager'); 
$moduleManager->loadModules(); 
$serviceManager->setAllowOverride(true); 

$application = $serviceManager->get('Application'); 
$event = new MvcEvent(); 
$event->setTarget($application); 
$event->setApplication($application) 
    ->setRequest($application->getRequest()) 
    ->setResponse($application->getResponse()) 
    ->setRouter($serviceManager->get('Router')); 

, a continuación, puede crear métodos estáticos en su caso de prueba para establecer y obtener el evento. ..

namespace My; 

class TestCase extends \Some\Basic\TestCase 
{ 
    protected static $_mvcEvent; 

    public static function setMvcEvent(MvcEvent $e) { 

     self::$_mvcEvent = $e; 
    } 

    public static function getMvcEvent() { 

     return self::$_mvcEvent; 
    } 
} 

... e inyectarlo a partir del archivo Bootstrap.php

My\TestCase::setMvcEvent($event); 

y en el método de configuración de la prueba simplemente hacer algo como esto

$this->_controller = new UserTokenController; 
$this->_controller->setEvent(self::getMvcEvent()); 
$this->_controller->setServiceLocator(
    self::getMvcEvent()->getApplication()->getServiceManager() 
); 

también inyectar petición etc. .desde evento-> aplicación al controlador aquí ...

+0

Después de todo he usado un enfoque un poco diferente (pero la idea principal es la misma, simplemente puse más lógica dentro de mi Bootstrap.php para phpunit). Pero el tuyo también funciona. –

+0

mina también hace mucho más, solo la redujo a los requisitos básicos –

+0

Hola Andreas. También estoy usando ZF2 + Doctrine2 y sigo tu método. Mientras se configura el ServiceLocator, parece que el evento no se propaga a los complementos de Controller: el enrutador, por ejemplo, se establece en el serviceLocator pero no en el complemento redirect(). ¿Alguna idea sobre cómo configurar esto? – Ross

0

Simplemente extienda su controlador desde \ Zend \ Test \ PHPUnit \ Controller \ AbstractHttpControllerTestCase

Es el localizador de servicios init y hace un montón de trabajo de otro controlador. Además de estar disponible el controlador afirma, la respuesta afirma, CSS afirma, etc. Los detalles con ejemplos se ven aquí http://framework.zend.com/manual/2.1/en/modules/zend.test.phpunit.html

Cuestiones relacionadas