Php 在Symfony2中使用条令测试控制器
我在Symony2中创建了一个非常简单的REST控制器,在控制器操作中插入/更新/删除数据库 有没有一种很好的方法可以在不污染生产数据库的情况下为这些控制器操作编写单元/集成测试?我是否必须使用不同的环境?或者框架供应商是否为此提出了建议 当前控制器示例:Php 在Symfony2中使用条令测试控制器,php,symfony,phpunit,symfony-2.1,Php,Symfony,Phpunit,Symfony 2.1,我在Symony2中创建了一个非常简单的REST控制器,在控制器操作中插入/更新/删除数据库 有没有一种很好的方法可以在不污染生产数据库的情况下为这些控制器操作编写单元/集成测试?我是否必须使用不同的环境?或者框架供应商是否为此提出了建议 当前控制器示例: public function postAction() { $json = $this->getRequest()->getContent(); $params = json_decode($json);
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()
);
}
}
在我看来,您应该绝对避免在测试中更改数据库 我最喜欢的实现方法是在测试客户机中注入实体管理器mock。例如:
public function testRest()
{
// create entity manager mock
$entityManagerMock = $this->getMockBuilder('Doctrine\ORM\EntityManager')
->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()
);
}
对于这个解决方案,您应该注意的一点是,您需要在每个请求之前注入模拟服务。这是因为客户机在每个请求之间重新启动内核(这意味着容器也在重建)
编辑:
我在controller测试中的GET方法是,我可以模拟实体存储库等,以便存根从db获取的每个数据,但这需要大量的工作,而且不是很舒服,所以我更喜欢在这种情况下(我的意思是,只有在我们谈到controller的测试时)从db实际获取真实数据。我所说的真实数据指的是用计算机创建的数据。只要我们不改变数据库,我们就可以依靠固定装置
但是,如果我们谈论的是在db(POST/PUT/DELETE方法)中更改数据,我总是使用mock。如果您使用em mock并对“perist”和“flush”方法设置适当的期望值,那么您可以确保在不修改任何数据库的情况下正确创建/更新/删除数据。下面是我要做的
在测试类中,添加$kernel静态变量,并创建一个在测试模式下加载内核的函数
protected static $kernel;
protected static $container;
public static function setUpBeforeClass()
{
self::$kernel = new \AppKernel('test', true);
self::$kernel->boot();
self::$container = self::$kernel->getContainer();
}
作为测试函数的第一行,调用self:setUpBeforeClass()
这使得symfony加载config_test.yml配置文件,您可以在那里定义不同的数据库连接,这是一种很好的方法,尤其是当您需要在数据库中包含一些测试数据时,使用单独的SQLite数据库和doctrineTextureBundle
PHP致命错误:在第759行的/files/custom\u www/antique crayon/preproduction/vendor/doctrine/orm/lib/doctrine/orm/EntityManager.PHP中对非对象调用成员函数getRepository()-如果我停止注入doctrine.orm.default\u entity\u manager
(当然,并注释掉期望值一次)然后它给出了绿色条(当然,然后保存到真正的DB,这是我们想要避免的)