Статьи

Совет: тестирование приложений Symfony с помощью одноразовой базы данных

Тестирование кода, который взаимодействует с базой данных, может быть огромной болью. Некоторые разработчики высмеивают абстракции базы данных и, следовательно, не проверяют фактический запрос. Другие создают тестовую базу данных для среды разработки, но это также может быть проблемой, если речь идет о непрерывной интеграции и поддержании состояния этой базы данных.

Логотип Symfony

Базы данных в памяти являются альтернативой этим опциям. Поскольку они существуют только в памяти приложения, они действительно одноразовые и отлично подходят для тестирования. К счастью, их очень легко настроить с помощью приложений Symfony, использующих Doctrine. Попробуйте прочитать наше руководство по функциональному тестированию с Symfony после этого, чтобы узнать о тестировании сквозного поведения приложения.

Конфигурация среды Symfony

Одной из наиболее мощных функций инфраструктуры Symfony является возможность создавать различные среды с их собственной уникальной конфигурацией. Разработчики Symfony могут упустить эту возможность, особенно когда речь идет о менее известной тестовой среде, которая здесь исследуется.

Руководство Symfony по освоению и созданию новых сред объясняет, как инфраструктура обрабатывает конфигурацию для различных сред, и показывает несколько полезных примеров. Файл конфигурации, который необходимо отредактировать для настройки одноразовых тестовых баз данных, — app/config/config_test.php При обращении к приложению в наборе тестов ядро ​​будет загружено с использованием среды тестирования, и этот файл конфигурации будет обработан.

Базы данных в памяти с доктриной

SQLite3 поддерживает базы данных в памяти, которые отлично подходят для тестирования. Используя их, приложение можно протестировать, фактически отправляя запросы SQL в работающую базу данных, избавляя от необходимости утомительно насмехаться над классами репозитория с предопределенным поведением. База данных будет новой в начале теста и полностью уничтожена в конце.

Чтобы переопределить стандартную конфигурацию подключения к доктрине, необходимо добавить следующие строки в файл конфигурации тестовой среды. Если в приложении настроено несколько подключений к доктрине, возможно, его необходимо слегка адаптировать для соответствия.

 # app/config/config_test.yml

doctrine:
    dbal:
        driver:  pdo_sqlite
        memory:  true
        charset: UTF8

Использование базы данных в тестовых классах

При использовании этой новой блестящей базы данных в памяти в тестовых классах сначала необходимо создать схему. Это означает создание таблиц из сущностей и загрузку любых приборов, необходимых для набора тестов.

Класс ниже может использоваться как учебник для начинающих, который выполняет большую часть этой работы. Это имеет тот же эффект, что и принудительное выполнение команды консоли обновления схемы доктрины.

 <?php

namespace Tests\AppBundle;

use Doctrine\ORM\EntityManager;
use Doctrine\ORM\Tools\SchemaTool;
use Symfony\Component\HttpKernel\KernelInterface;

class DatabasePrimer
{
    public static function prime(KernelInterface $kernel)
    {
        // Make sure we are in the test environment
        if ('test' !== $kernel->getEnvironment()) {
            throw new \LogicException('Primer must be executed in the test environment');
        }

        // Get the entity manager from the service container
        $entityManager = $kernel->getContainer()->get('doctrine.orm.entity_manager');

        // Run the schema update tool using our entity metadata
        $metadatas = $entityManager->getMetadataFactory()->getAllMetadata();
        $schemaTool = new SchemaTool($entityManager);
        $schemaTool->updateSchema($metadatas);

        // If you are using the Doctrine Fixtures Bundle you could load these here
    }
}

Если для проверки класса требуется менеджер сущностей, необходимо применить учебник:

 <?php

namespace Tests\AppBundle;

use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
use Tests\AppBundle\DatabasePrimer;

class FooTest extends KernelTestCase
{
    public function setUp()
    {
        self::bootKernel();

        DatabasePrimer::prime(self::$kernel);
    }

    public function testFoo()
    {
        $fooService = self::$kernel->getContainer()->get('app.foo_service');

        // ...
    }
}

В приведенном выше примере контейнер используется для получения тестируемой службы. Если эта служба зависит от менеджера сущностей, она будет создана с тем же менеджером сущностей, который заполнен в методе setUp Если требуется больше контроля, возможно, для насмешки над другой зависимостью, менеджер сущностей всегда можно извлечь из контейнера и использовать для создания экземпляра класса, который нуждается в тестировании вручную.

Также может быть полезно использовать пакет Doctrine Fixtures Bundle для заполнения базы данных тестовыми данными, но это будет зависеть от вашего варианта использования.