Functional Test - Mock service does not persist in service container

限于喜欢 提交于 2019-12-23 17:16:06

问题


I am hoping someone can shed some light on this issue I am facing.

[PROBLEM]

I have mocked out doctrine.orm.default_entity_manager service in my functional unit test. I inject this into the client service container so that I do not have to hit my DB during the course of my functional test. For my test that just involve a GET request I am able to verify that the controller I am testing is using my mocked service.

However, if I attempt to do a POST request by using the crawler with a form submission my mocked service does not persist. After the initial GET request the client seems to just inject doctrine.orm.default_entity_manager service again as it needs it and not my mocked version that I set in the clients service container.

In summary, during the GET request my mocked service is being used, but during the POST request EntityManager5144076565ee8_546a8d27f194334ee012bfe64f629947b07e4919__CG__\Doctrine\ORM\EntityManager is being used. [SEE CODE SNIPPET BELOW]

[QUESTION]

Is it possible to do what I am asking? I would like to have ALL my requests use the mocked service I defined. I want to have a functional test but avoid writing or reading from the database.

[SAMPLE CODE]

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

回答1:


The issue here is that the kernel is booted after (during) every request:

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

So you need to replace doctrine with your mock after each request:

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

An easier way to use your mock globally would be to override the doctrine settings in config_test.yml

 orm:
        default_entity_manager:  Acme/MyBundle/Test/MockDoctrineEM

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



来源:https://stackoverflow.com/questions/15606191/functional-test-mock-service-does-not-persist-in-service-container

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!