2012-09-14 9 views
9

ここは私の状況です。私はZend Framework 2アプリケーションを開発しています。私はDoctrineモジュールを使ってMySQLデータベースと通信しています。アプリケーションで正常に動作しています。コントローラ内のサービスロケータからエンティティマネージャをロードできます。Zend Framework 2 Doctrine 2モジュール - コントローラユニットテストのサービスロケータなし

しかし、私のコントローラユニットテスト内で、サービスロケータが存在せず、そのためのデータベースを扱うすべてのテストは、このようなエラーメッセージで失敗している:

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

私はこの方法に問題が絞られています:

$this->getServiceLocator() 

私のコントローラでは動作しますが、ユニットテストではNULLを返します。

これは私の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', 
     ), 
    ), 
); 

データベース接続の詳細をマイlocal.phpファイルのファイル:私は私のmodule.config.phpで

<?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', 
       ), 
      ), 
     ), 
    ), 
); 

'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' 
      ), 
     ), 
    ), 
), 

私のコントローラでは、エンティティマネージャを取得するこの方法があります:

private $_em; 

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

私のユニットがテストします。ここでは、ブートストラップファイルには、次のとおりです。私のコントローラテストの

<?php 

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

とセットアップ方法は以下のようになります。

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

あるすべてのテストを:

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); 
} 

例コントローラユニットテストは、次にようになります。データベースに接続していない場合は合格となります。私は、エンティティマネージャを使用しています試験は、このエラーにかかわらず、失敗する:

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

これは、19行目です:

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

そして、それは失敗だ理由は$this->getServiceLocator()戻りNULLということです。

このアイデアを解決する方法はありますか?あなたは、イベントを設定して得るためにあなたのテストケースの静的メソッドを作成することができ

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')); 

答えて

6

いけない」これはあなたのbootstrap.phpの

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

が、このような何かをINSありません。 ..

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; 
    } 
} 

...と

My\TestCase::setMvcEvent($event); 

とテストのあなたのセットアップ方法にbootstrap.phpのファイルから、それを注入は、単にこの

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

のようなものも、リクエストなどを注入します。イベント - >アプリケーションからここにコントローラへ...

+0

結局のところ、私はちょっとしたアプローチを使いました(しかし、主なアイデアは同じです。 phpunitのBootstrap.php)。しかし、あなたもうまくいきます。 –

+0

鉱山も多くのことを行い、ちょうどそれを基本的な要件に減らしました –

+0

こんにちはアンドレアス。私はZF2 + Doctrine2も使用しており、あなたの方法に従っています。 ServiceLocatorが設定されている間、イベントはControllerプラグインには伝播していないようです。たとえばルータはserviceLocatorでは設定されていますが、redirect()プラグインでは設定されていません。これを設定する方法に関するアイデアはありますか? – Ross

0

コントローラーを \ Zend \ Test \ PHPUnit \ Controller \ AbstractHttpControllerTestCase

これはinitサービスのロケータであり、他のControllerの仕事をたくさんしています。コントローラアサート、レスポンスアサート、CSSアサートなども可能になりますhttp://framework.zend.com/manual/2.1/en/modules/zend.test.phpunit.html

関連する問題