功能测试 - Mock服务不会保留在服务容器中 [英] Functional Test - Mock service does not persist in service container

查看:106
本文介绍了功能测试 - Mock服务不会保留在服务容器中的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



[问题]



我在我的功能单元测试中嘲笑了doctrine.orm.default_entity_manager服务。我将这个注入到客户端服务容器中,这样我在功能测试过程中就不必打DB了。对于我的测试,只需要一个GET请求,我可以验证我正在测试的控制器是否使用我的嘲笑服务。



但是,如果我尝试做一个POST通过使用履带式提交表单提交请求,我的嘲笑服务不会持续。在初始GET请求之后,客户端似乎只是根据需要再次注入doctrine.orm.default_entity_manager服务,而不是我在客户端服务容器中设置的嘲笑版本。总而言之,在GET请求期间,我的嘲笑服务正在被使用,但在POST请求期间,正在使用EntityManager5144076565ee8_546a8d27f194334ee012bfe64f629947b07e4919__CG__\Doctrine\ORM\EntityManager。
[查看下面的代码下载]



[QUESTION]



可以做我所要求的吗?我想让我的所有请求都使用我定义的嘲笑服务。我想要一个功能测试,但是避免从数据库中写入或读取。



[样本代码]



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

$ entityRepository-> expects($ this-> any()) - >方法('findBy')
- >将($ this-> returnValue ()));

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

$ em-> expects($ this-> any()) - >方法('flush')
- >将($ this-> returnValue(FALSE ));

$ em-> expects($ this-> any()) - >方法('persist')
- >将($ this-> returnValue(FALSE ));

$ em-> expects($ this-> any()) - >方法('getRepository')
- >将($ this-> returnValue entityRepository));

$ em-> expects($ this-> any()) - >方法('getClassMetadata')
- >将($ this-> returnValue ClassMetadata( 测试)));

//创建测试客户端。
$ client = static :: createClient();

//将实体模拟进入服务容器。
$ client-> getContainer()
- > set('doctrine.orm.default_entity_manager',$ em,'container');

//定义请求
$ crawler = $ client-> request('GET','/ locations / types / add');

//验证一些东西
$ form = $ crawler-> selectButton('submit') - > form();
$ form ['location_type [title]'] =TEST TITLE;
$ form ['location_type [description]'] =TEST DESCP;

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


解决方案

这里的问题是内核启动后期间)每个请求:

 保护功能doRequest($ request)
{
//避免关闭内核,如果没有执行请求
// WebTestCase :: createClient()启动内核但是不处理请求
如果($ this-> hasPerformedRequest){
$ this - >内核级>关闭();
} 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



所以你需要在每个请求后用你的模拟替换原则:

  //将实体模拟器插入服务容器。 
$ client-> getContainer()
- > set('doctrine.orm.default_entity_manager',$ em,'container');

//定义请求
$ crawler = $ client-> request('GET','/ locations / types / add');

//将实体模拟进入服务容器。
$ client-> getContainer()
- > set('doctrine.orm.default_entity_manager',$ em,'container');

全局使用你的模拟的更简单的方法是覆盖config_test.yml中的原则设置



  orm:
default_entity_manager:Acme / MyBundle / Test / MockDoctrineEM
pre>

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


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

解决方案

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

这篇关于功能测试 - Mock服务不会保留在服务容器中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆