Найти в Дзене
Symfony Topsite Web

Настройка тестовой базы данных в Symfony

Настройка тестовой базы данных в Symfony может быть сложной задачей, я решил написать краткое руководство, которое поможет вам в этом процессе. Следуя этим шагам, вам не придется испытывать трудности. Прежде чем мы начнем, нам нужно добавить несколько пакетов в наш проект. Во-первых, давайте установим пакет «liip/test-fixtures-bundle», который предоставляет базовые классы для функциональных тестов и помогает в настройке тестовых баз данных и загрузке фикстур. composer require --dev liip/test-fixtures-bundle Этот пакет совместим с любой базой данных, поддерживаемой Doctrine ORM, такой как MySQL, PostgreSQL, SQLite и других. Если вы используете MongoDB, вам следует вместо этого использовать «DoctrineMongoDBBundle».
Далее установим связку «orm-fixtures», необходимую для загрузки фикстур в базу. composer require --dev orm-fixtures Предполагая, что вы уже установили пакет PHPUnit и Doctrine, мы можем приступить к настройке нашей тестовой базы данных. Откройте файл «.env.test» и добавьте сл

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

Во-первых, давайте установим пакет «liip/test-fixtures-bundle», который предоставляет базовые классы для функциональных тестов и помогает в настройке тестовых баз данных и загрузке фикстур.

composer require --dev liip/test-fixtures-bundle

Этот пакет совместим с любой базой данных, поддерживаемой Doctrine ORM, такой как MySQL, PostgreSQL, SQLite и других. Если вы используете MongoDB, вам следует вместо этого использовать «DoctrineMongoDBBundle».
Далее установим связку «orm-fixtures», необходимую для загрузки фикстур в базу.

composer require --dev orm-fixtures

Предполагая, что вы уже установили пакет PHPUnit и Doctrine, мы можем приступить к настройке нашей тестовой базы данных. Откройте файл «.env.test» и добавьте следующий код, чтобы определить среду и URL-адрес базы данных.

APP_ENV = test
DATABASE_URL = "mysql://username:password@127.0.0.1:3306/dbname?serverVersion=8&charset=utf8mb4"

Теперь мы можем создать нашу тестовую базу данных, выполнив следующие команды.

symfony console doctrine:database:create --env=test
symfony console doctrine:schema:update --env=test --force

Проверьте свой PHPMyAdmin, чтобы убедиться, что тестовая база данных создана успешно. Теперь позвольте мне показать вам, как выполнять тестирование базы данных с фикстурами и без них.

Прежде чем мы продолжим, обязательно обновите файл «doctrine.yml» в каталоге config, включив в него имя вашей тестовой базы данных:

when@test:
doctrine:
dbal:
dbname: 'dbname_test'

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

class ProductTest extends KernelTestCase
{

public function testProductIsInsertedSuccessfully() : void{

self::bootKernel();
$entityManager = static::$kernel->getContainer()
->get('doctrine')
->getManager();

$product = new Product();
$product->setName('Test Product');
$product->setPrice(11.99);
$product->setSlug('new_slug');

$entityManager->persist($product);
$entityManager->flush();

$insertedProduct = $entityManager->getRepository(Product::class)->findOneBy([
'name' => 'Test Product',
]);

self::assertNotNull($insertedProduct);
self::assertEquals('Test Product', $insertedProduct->getName());
self::assertEquals(11.99, $insertedProduct->getPrice());

}
}

Вот описание того, что делает код:

Класс ProductTestextends KernelTestCase — это базовый класс, предоставляемый Symfony для целей тестирования.

  1. Метод testProductIsInsertedSuccessfully представляет собой тестовый пример, который проверяет успешную вставку продукта.
  2. self::bootKernel() загружает ядро ​​Symfony для тестовой среды.
  3. $entityManager получается из контейнера, который отвечает за управление сущностями и выполнение операций с базой данных.
  4. Product создается новый объект и устанавливаются его свойства ( name, price, slug).
  5. $entityManager->persist($product) используется, чтобы указать менеджеру сущностей управлять Product сущностью и подготовить ее к вставке в базу данных.
  6. $entityManager->flush() сбрасывает все ожидающие изменения в базу данных, включая вставку продукта.
  7. $entityManager->getRepository(Product::class)->findOneBy() используется для извлечения вставленного продукта из базы данных на основе указанных критериев (name в данном случае).
  8. Несколько утверждений выполняются с использованием self::assertNotNull и self::assertEquals для проверки существования вставленного продукта и соответствия его свойств ожидаемым значениям.

Теперь перейдем к тестированию базы данных с помощью фикстур. Мы создадим класс для загрузки продукта в базу данных.

namespace App\DataFixtures;

use App\Entity\Product;
use Doctrine\Bundle\FixturesBundle\Fixture;
use Doctrine\Persistence\ObjectManager;

class ProductFixtures extends Fixture
{

public function load(ObjectManager $manager)
{

$product = new Product();
$product->setName('product 1');
$product->setPrice(40);
$product->setSlug('product/slug/1');
$manager->persist($product);
$manager->flush();

}
}

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

symfony console doctrine:fixtures:load --env=test

Независимо от того, запускаете ли вы команду или нет, фикстуры будут загружаться в каждом тесте.

Однако, прежде чем продолжить, нам нужно установить еще один пакет под названием «dama/doctrine-test-bundle». Этот пакет гарантирует, что данные восстанавливаются перед каждым тестом, что считается передовой практикой. Установите его, запустив

composer require --dev dama/doctrine-test-bundle

Чтобы включить пакет, откройте файл «phpunit.xml.dist» и добавьте следующий код.

< extensions >
< extension class = "DAMA\DoctrineTestBundle\PHPUnit\PHPUnitExtension" />
</ extensions >

Теперь мы готовы создать наши тесты с фикстурами.

namespace App\Tests;

use App\DataFixtures\ProductFixtures;
use App\Entity\Product;
use Doctrine\ORM\EntityManagerInterface;
use Liip\TestFixturesBundle\Services\DatabaseToolCollection;
use Liip\TestFixturesBundle\Services\DatabaseTools\AbstractDatabaseTool;
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;


class ProductFixtureTest extends KernelTestCase
{
protected AbstractDatabaseTool $databaseTool;
protected EntityManagerInterface $entityManager;

public function setUp(): void
{
parent::setUp();
self::bootKernel();
$this->entityManager = static::$kernel->getContainer()->get('doctrine')->getManager();
$this->databaseTool = static::$kernel->getContainer()->get(DatabaseToolCollection::class)->get();
}
public function testDeleteProduct(): void
{
$this->databaseTool->loadFixtures([
ProductFixtures::class
]);
$insertedProduct = $this->entityManager->getRepository(Product::class)->findOneBy(['slug' => 'product/slug/1',]);
$this->entityManager->getRepository(Product::class)->remove($insertedProduct,true);
$deletedProduct = $this->entityManager->getRepository(Product::class)->findOneBy(['slug' => 'product/slug/1',]);
$this->assertNull($deletedProduct);
}
public function testProductExist(): void
{
$this->databaseTool->loadFixtures([ProductFixtures::class]);
$insertedProduct = $this->entityManager->getRepository(Product::class)->findOneBy([
'slug' => 'product/slug/1', ]);
self::assertNotNull($insertedProduct);
}
}

Метод setUp() — это специальный метод в PHPUnit, который выполняется перед каждым тестовым методом. setUp() в этом методе сначала вызывается родительский метод, который настраивает тестовую среду.

Метод testDeleteProduct() проверяет удаление продукта. Сначала loadFixtures() вызывается метод из инструмента базы данных для загрузки необходимых для теста фикстур (данных), в данном случае класса ProductFixtures. Затем менеджер сущностей используется для поиска продукта с определенным ярлыком («продукт/слаг/1»). Метод remove() вызывается в репозитории для удаления найденного продукта. Затем снова используется диспетчер сущностей, чтобы попытаться найти удаленный продукт. Наконец, assertNull() метод используется для утверждения, что удаленный продукт является нулевым, что указывает на то, что он был успешно удален.

Метод testProductExist() проверяет, существует ли продукт. Как и в предыдущем тесте, фикстуры загружаются с помощью loadFixtures() метода. Затем диспетчер сущностей используется для поиска продукта с указанным ярлыком. Этот assertNotNull() метод используется для подтверждения того, что продукт не является нулевым, указывая на то, что он существует, а это означает, что данные восстанавливаются перед запуском каждого теста.

Я надеюсь, что это руководство поможет вам! Удачи вам в ваших тестах.