3

私が直面しているこの問題について、誰かが光を当ててくれることを願っています。

[問題]

機能ユニットテストでdoctrine.orm.default_entity_managerサービスをモックアウトしました。これをクライアントサービスコンテナに挿入して、機能テスト中にDBをヒットする必要がないようにします。GETリクエストのみを含むテストでは、テストしているコントローラーがモックサービスを使用していることを確認できます。

ただし、フォーム送信でクローラーを使用してPOSTリクエストを実行しようとすると、モックされたサービスが持続しません。最初のGETリクエストの後、クライアントは、クライアントサービスコンテナに設定したモックバージョンではなく、必要に応じてdoctrine.orm.default_entity_managerサービスを再度注入するようです。

要約すると、GETリクエストではモックサービスが使用されていますが、POSTリクエストではEntityManager5144076565ee8_546a8d27f194334ee012bfe64f629947b07e4919__CG __ \ Doctrine \ ORM\EntityManagerが使用されています。 [以下のコードスニペットを参照]

[質問]

私が求めていることをすることは可能ですか?すべてのリクエストで、定義したモックサービスを使用したいと思います。機能テストをしたいのですが、データベースへの書き込みや読み取りは避けてください。

[サンプルコード]

    // Mocks
    $entityRepository = $this
    ->getMockBuilder('Doctrine\ORM\EntityRepository')
    ->setMethods(array('findby'))->disableOriginalConstructor()
    ->getMock();

    $entityRepository->expects($this->any())->method('findBy')
    ->will($this->returnValue(array()));

    $em = $this->getMockBuilder('Doctrine\ORM\EntityManager')
    ->setMethods(
    array('getRepository', 'getClassMetadata', 'flush',
    'persist'))->disableOriginalConstructor()
    ->getMock();

    $em->expects($this->any())->method('flush')
    ->will($this->returnValue(FALSE));

    $em->expects($this->any())->method('persist')
    ->will($this->returnValue(FALSE));

    $em->expects($this->any())->method('getRepository')
    ->will($this->returnValue($entityRepository));

    $em->expects($this->any())->method('getClassMetadata')
    ->will($this->returnValue(new ClassMetadata("test")));

    // Create test client.
    $client = static::createClient();

    // Inject entity mock into service container.
    $client->getContainer()
    ->set('doctrine.orm.default_entity_manager', $em, 'container');

    // Define request
    $crawler = $client->request('GET', '/locations/types/add');

    // Verify a few things
    $form = $crawler->selectButton('submit')->form();
    $form['location_type[title]'] = "TEST TITLE";
    $form['location_type[description]'] = "TEST DESCP";

    $crawler = $client->submit($form);
4

1 に答える 1

2

ここでの問題は、すべての要求の後で(実行中に)カーネルが起動されることです。

protected function doRequest($request)
{
    // avoid shutting down the Kernel if no request has been performed yet
    // WebTestCase::createClient() boots the Kernel but do not handle a request
    if ($this->hasPerformedRequest) {
        $this->kernel->shutdown();
    } else {
        $this->hasPerformedRequest = true;
    }

    if ($this->profiler) {
        $this->profiler = false;

        $this->kernel->boot();
        $this->kernel->getContainer()->get('profiler')->enable();
    }

https://github.com/symfony/symfony/blob/master/src/Symfony/Bundle/FrameworkBundle/Client.php

したがって、各リクエストの後に、教義をモックに置き換える必要があります。

// Inject entity mock into service container.
$client->getContainer()
->set('doctrine.orm.default_entity_manager', $em, 'container');

// Define request
$crawler = $client->request('GET', '/locations/types/add'); 

// Inject entity mock into service container.
$client->getContainer()
->set('doctrine.orm.default_entity_manager', $em, 'container');

モックをグローバルに使用する簡単な方法は、config_test.ymlの教義設定をオーバーライドすることです。

 orm:
        default_entity_manager:  Acme/MyBundle/Test/MockDoctrineEM

http://symfony.com/doc/master/reference/configuration/doctrine.html

于 2013-03-25T17:59:11.133 に答える