在 Symfony2 中使用 Doctrine 测试控制器 [英] Testing Controllers in Symfony2 with Doctrine

查看:25
本文介绍了在 Symfony2 中使用 Doctrine 测试控制器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在 Symony2 中创建了一个非常简单的 REST 控制器,在控制器操作中使用数据库插入/更新/删除.

I have created a very simple REST controller in Symony2 with Database insert/updates/deletes in the controller actions.

有没有一种很好的方法可以在不污染生产数据库的情况下为这些控制器操作编写单元/集成测试?我是否必须在不同的环境中工作 - 或者框架供应商是否为此提出了建议的方法?

Is there a nice way to write unit/integration tests for these controller actions without polluting the production database? Do I have to work with different environments - or is there a proposed way from the framework vendor for this?

电流控制器示例:

public function postAction()
{
    $json = $this->getRequest()->getContent();
    $params = json_decode($json);
    $name = $params->name;
    $description = $params->description;

    $sandbox = new Sandbox();
    $sandbox->setName($name);
    $sandbox->setDescription($description);
    $em = $this->getDoctrine()->getManager();
    $em->persist($sandbox);
    $em->flush();

    $response = new Response('/sandbox/'.$sandbox->getId());
    $response->setStatusCode(201);
    return $response;
}

当前测试示例:

class SandboxControllerTest extends WebTestCase
{

    public function testRest()
    {
        $client = static::createClient();

        $crawler = $client->request('POST', '/service/sandbox', array(), array(), array(), json_encode(array('name' => 'TestMe', 'description' => 'TestDesc')));

        $this->assertEquals(
                201, $client->getResponse()->getStatusCode()
        );
    }
}

推荐答案

在我看来,您绝对应该避免在测试中更改数据库.

In my opinion you should definitely avoid change database with your tests.

我最喜欢的实现方式是在测试客户端中注入实体管理器模拟.例如:

My favourite way to achieve this is inject entity manager mock inside a test client. For example:

public function testRest()
{
    // create entity manager mock
    $entityManagerMock = $this->getMockBuilder('DoctrineORMEntityManager')
        ->setMethods(array('persist', 'flush'))
        ->disableOriginalConstructor()
        ->getMock();

    // now you can get some assertions if you want, eg.:
    $entityManagerMock->expects($this->once())
        ->method('flush');

    // next you need inject your mocked em into client's service container
    $client = static::createClient();
    $client->getContainer()->set('doctrine.orm.default_entity_manager', $entityManagerMock);

    // then you just do testing as usual
    $crawler = $client->request('POST', '/service/sandbox', array(), array(), array(), json_encode(array('name' => 'TestMe', 'description' => 'TestDesc')));

    $this->assertEquals(
            201, $client->getResponse()->getStatusCode()
    );
}

您应该注意此解决方案的一件事是您需要在每个请求之前注入您的模拟服务.这是因为客户端在每次请求之间重新启动内核(这意味着容器也在重建).

One thing with this solution which you should be aware is that you need inject your mocked service before each request. This is because the client reboots a kernel between each request (which means that the container is rebuild as well).

我在控制器测试中的 GET 方法是,我可以模拟实体存储库等,以便对从 db 获取的每个数据进行存根,但工作量很大而且不是很舒服,所以我更喜欢这种情况(我的意思是只如果我们谈论控制器的测试)实际上是从数据库中获取真实数据.我所说的真实数据是指用学说装置创建的数据.只要我们不改变数据库,我们就可以依赖fixture.

My GET approach in controller's tests is that I can mock entity repositories and so on in order to stub every getting data from db but it's a lot of work and it's not very comfortable, so I prefer in this case (I mean only if we speak about controller's test) actually getting real data from db. By real data I mean data created with doctrine fixtures. And as long as we don't change database we can depend on the fixtures.

但是如果我们谈论更改数据库中的数据(POST/PUT/DELETE 方法),我总是使用模拟.如果您将使用 em mock 并对perist"和flush"方法设置适当的期望,您可以确保数据被正确创建/更新/删除,而无需对数据库进行任何修改.

But if we are speaking about changing data inside db (POST/PUT/DELETE methods) I always use mocks. If you'll use em mock and set appropriate expectations on "perist" and "flush" methods, you can be sure that the data is correctly created/updated/deleted actually without any database's modifications.

这篇关于在 Symfony2 中使用 Doctrine 测试控制器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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