在Symfony应用程序中使用Doctrine DataFixtures和用PHPUnit测试动态响应

140 阅读1分钟

下面的例子有助于我们在用PHPUnit测试Symfony控制器时处理动态响应内容。在这个例子中,idcreated_at 字段是动态的,所以每个响应会有不同的值。之所以数据总是动态的,是因为它们是由Doctrine DataFixtures加载的。

流程

  1. setUp 方法在运行每个测试案例之前重新加载数据固定装置。

  2. replaceDynamicData 方法将任何动态数据替换为指定规则的静态数据。

  3. tearDownAfterClass 方法在整个测试套件结束时重新加载数据夹具。

配置

这些配置是用来隔离test,devprod 环境的,所以每个环境都有自己的数据库,如api_test,api_devapi

.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/phpunitsymfony/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)