10

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

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

致命的なエラー: get()19 行目の /Users/richardknop/Projects/myproject/module/Api/src/Api/Controller/UserController.php の非オブジェクトに対するメンバー関数の呼び出し

問題を次の方法に絞り込みました。

$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 ファイル:

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

私のmodule.config.phpには次のものがあります:

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

私のコントローラーテストのsetUpメソッドは次のようになります:

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

コントローラー単体テストの例は次のようになります。

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

データベースに接続していないすべてのテストに合格しています。エンティティ マネージャーを使用しているテストは失敗しますが、次のエラーが表示されます。

致命的なエラー: get()19 行目の /Users/richardknop/Projects/myproject/module/Api/src/Api/Controller/UserController.php の非オブジェクトに対するメンバー関数の呼び出し

これは19行目です:

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

そして、それが失敗する理由は、それが$this->getServiceLocator()返されることNULLです。

この問題を解決する方法はありますか?

4

2 に答える 2

6

あなたのbootstrap.phpでこれをしないでください

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

しかし、このようなもの:

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

次に、テストケースで静的メソッドを作成して、イベントを設定および取得できます...

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

...そして、bootstrap.php ファイルから挿入します

My\TestCase::setMvcEvent($event); 

そして、テストのsetUpメソッドで、次のようなことをするだけです

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

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

于 2012-09-18T21:03:58.763 に答える
1

\Zend\Test\PHPUnit\Controller\AbstractHttpControllerTestCase からコントローラを拡張するだけです

これは init サービス ロケーターであり、他の多くのコントローラーの仕事を行います。コントローラーアサート、レスポンスアサート、CSSアサートなども利用可能になります。例を含む詳細はこちらをご覧ください http://framework.zend.com/manual/2.1/en/modules/zend.test.phpunit.html

于 2014-05-16T12:50:03.493 に答える