下面的例子有助于我们在用PHPUnit测试Symfony控制器时处理动态响应内容。在这个例子中,id 和created_at 字段是动态的,所以每个响应会有不同的值。之所以数据总是动态的,是因为它们是由Doctrine DataFixtures加载的。
流程
-
setUp方法在运行每个测试案例之前重新加载数据固定装置。 -
replaceDynamicData方法将任何动态数据替换为指定规则的静态数据。 -
tearDownAfterClass方法在整个测试套件结束时重新加载数据夹具。
配置
这些配置是用来隔离test,dev 和prod 环境的,所以每个环境都有自己的数据库,如api_test,api_dev 和api 。
.env.dist
APP_ENV=dev
DATABASE_URL=mysql://root:root@127.0.0.1:3306/api
config/packages/doctrine.yaml
doctrine:
dbal:
...
url: '%env(resolve:DATABASE_URL)%'
config/packages/test/doctrine.yaml
doctrine:
dbal:
url: '%env(resolve:DATABASE_URL)%_%kernel.environment%'
config/packages/dev/doctrine.yaml
doctrine:
dbal:
url: '%env(resolve:DATABASE_URL)%_%kernel.environment%'
phpunit.xml.dist
xsi:noNamespaceSchemaLocation="http://schema.phpunit.de/6.1/phpunit.xsd"
backupGlobals="false"
colors="true"
bootstrap="vendor/autoload.php">
tests
src
安装
确保你已经安装了phpunit/phpunit 和symfony/browser-kit composer软件包。
测试文件
摘要测试
declare(strict_types=1);
namespace App\Tests;
use App\DataFixtures\CountryFixtures;
use Doctrine\Common\DataFixtures\Executor\ORMExecutor;
use Doctrine\Common\DataFixtures\Loader;
use Doctrine\Common\DataFixtures\Purger\ORMPurger;
use Symfony\Bundle\FrameworkBundle\Client;
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
class AbstractTest extends WebTestCase
{
/** @var Client $client */
protected $client;
public static function tearDownAfterClass()
{
self::reloadDataFixtures();
}
protected function setUp()
{
self::reloadDataFixtures();
$this->client = static::createClient();
}
protected function replaceDynamicData(string $data): string
{
return preg_replace(
[
'/"id":\d/',
'/\b(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})\+(\d{4})\b/',
],
[
'"id":AUTO_ID',
'DATE_ISO8601',
],
$data
);
}
private static function reloadDataFixtures(): void
{
$kernel = static::createKernel();
$kernel->boot();
$entityManager = $kernel->getContainer()->get('doctrine')->getManager();
$loader = new Loader();
foreach (self::getFixtures() as $fixture) {
$loader->addFixture($fixture);
}
$purger = new ORMPurger();
$purger->setPurgeMode(ORMPurger::PURGE_MODE_DELETE);
$executor = new ORMExecutor($entityManager, $purger);
$executor->execute($loader->getFixtures());
}
private static function getFixtures(): iterable
{
return [
new CountryFixtures(),
];
}
}
CountryControllerTest
declare(strict_types=1);
namespace App\Tests\Controller;
use App\Tests\AbstractTest;
class CountryControllerTest extends AbstractTest
{
/**
* @test
* @dataProvider getAllDataProvider
*/
public function get_all_returns_valid_response(int $code, string $body)
{
$this->client->request('GET', '/api/v1/countries');
$this->assertSame($code, $this->client->getResponse()->getStatusCode());
$this->assertSame(
$this->replaceDynamicData(json_encode(json_decode($body, true))),
$this->replaceDynamicData($this->client->getResponse()->getContent())
);
}
public function getAllDataProvider(): iterable
{
return [
[
'$code' => 200,
'$body' => <<[
{
"id": 1,
"code": "gb",
"name": "Great Britain",
"createdAt": "2000-10-29T21:57:00+0100"
},
{
"id": 2,
"code": "tr",
"name": "Turkey",
"createdAt": "2001-11-30T22:58:01+0200"
},
{
"id": 3,
"code": "de",
"name": "Germany",
"createdAt": "2002-12-31T23:59:02+0300"
}
]
EOT
]
];
}
}
测试
$ vendor/bin/phpunit --filter CountryControllerTest tests/Controller/CountryControllerTest.php
PHPUnit 7.1.5 by Sebastian Bergmann and contributors.
. 1 / 1 (100%)
Time: 1.77 seconds, Memory: 22.00MB
OK (1 test, 2 assertions)