symfony 4 - 针对不同数据测试命令

问题描述

我有一个数据库上运行的命令,然后测试是否有任何公司有重复的名称,然后输出用户以进行任何补救。

每次测试我想做的是:

  • 数据库更改为指定的一组公司,例如10 companies with 5 of those having duplicate names 或例如10 companies with 5 having null names
  • 运行该测试

通常,如果这是一个函数,我可以在注释中使用数据提供者来提供不同的数据进行测试,例如

     * @dataProvider provideFoo
     * @param $data
     */
    public function testFooBar($data) {...

但是命令没有参数/参数,所以我想我每次都必须更新数据库

这可以用夹具来完成,还是我应该在每次测试中添加新公司,例如:

public function testFooBar($data) {
  $company1 = (new Company())->setName('Company 1');
  $this->entityManager->persist($company1);
  $this->entityManager->flush();
  
  $commandTester->execute([]);
  // rest of test
}

我应该补充 - 数据库非常大,删除和重置需要几个小时。

** 编辑 ** 我发现了这个问题,它似乎帮助我建立了测试数据库,我将继续看看现在测试数据库是否启动,我是否可以让装置工作:How to setup a database for test environment in Symfony 4

解决方法

我设法使用这个让它工作:

// tests/Command/FindDuplicatedCompaniesCommandTest.php:
<?php declare(strict_types=1);

namespace App\Tests\Command;

use App\DataFixtures\DuplicatedCompaniesFixtures;
use App\Tests\FixturesTrait;
use Symfony\Bundle\FrameworkBundle\Console\Application;
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
use Symfony\Component\Console\Tester\CommandTester;

class FindDuplicatedCompaniesCommandTest extends KernelTestCase
{
    use FixturesTrait;

    public function testExecuteDuplicates()
    {
        $kernel = static::createKernel();
        $application = new Application($kernel);
        $command = $application->find('app:find:duplicated-companies');
        $commandTester = new CommandTester($command);

        $this->addFixture(new DuplicatedCompaniesFixtures());
        $this->executeFixtures();

        $commandTester->execute([]);

        $output = $commandTester->getDisplay();

        $this->assertStringContainsString('Detected name',$output);
        $this->assertStringContainsString('Company 3',$output);
        $this->assertStringContainsString('Company 1',$output);
        $this->assertStringNotContainsString('violations',$output);
        $this->assertStringNotContainsString('No duplicates',$output);
    }

    protected function setUp(): void
    {
        self::bootKernel();
    }
}

// src/DataFixtures/DuplicatedCompaniesFixtures.php
<?php declare(strict_types=1);

namespace App\DataFixtures;

use App\Entity\Company;
use DateTimeImmutable;
use Doctrine\Bundle\FixturesBundle\Fixture;
use Doctrine\Persistence\ObjectManager;

/**
 * Class DuplicatedCompaniesFixtures
 * @package App\DataFixtures
 */
class DuplicatedCompaniesFixtures extends Fixture
{
    /**
     * @const CO_1_REFERENCE
     */
    public const CO_1_REF = 'COONE';

    /**
     * @const CO_2_REFERENCE
     */
    public const CO_2_REF = 'COTWO';

    /**
     * @const CO_3_REFERENCE
     */
    public const CO_3_REF = 'COTHREE';

    /**
     * @const CO_4_REFERENCE
     */
    public const CO_4_REF = 'COFOUR';

    /**
     * @param ObjectManager $manager
     */
    public function load(ObjectManager $manager)
    {
        $company1 = (new Company())
            ->setName('Company 1')
            ->setAlphaKey('COMPANYONE')
            ->setUpdatedAt(new DateTimeImmutable());
        $company2 = (new Company())
            ->setName('Company 1')
            ->setAlphaKey('COMPANYONE')
            ->setUpdatedAt(new DateTimeImmutable());
        $company3 = (new Company())
            ->setName('Company 3')
            ->setAlphaKey('COMPANYTHREE')
            ->setUpdatedAt(new DateTimeImmutable());
        $company4 = (new Company())
            ->setName('Company 3')
            ->setAlphaKey('COMPANYFOUR')
            ->setUpdatedAt(new DateTimeImmutable());

        $manager->persist($company1);
        $manager->persist($company2);
        $manager->persist($company3);
        $manager->persist($company4);
        $manager->flush();
        $this->addReference(self::CO_1_REF,$company1);
        $this->addReference(self::CO_2_REF,$company2);
        $this->addReference(self::CO_3_REF,$company3);
        $this->addReference(self::CO_4_REF,$company4);
    }
}

那样,我可以在文件中为每个测试添加不同的夹具,例如如果我想对名称违规进行单独的测试,我会添加 src/DataFixtures/NameViolationCompaniesFixtures.php 并在测试中调用它。