ben-rowan/doctrine-assert

基于 Doctrine2 的 PHPUnit 数据库断言集合

v0.1.0 2019-08-03 06:22 UTC

This package is not auto-updated.

Last update: 2024-09-23 07:08:55 UTC


README

一组用于您的 Doctrine 实体的 PHPUnit 数据库断言。

安装

composer require --dev ben-rowan/doctrine-assert

使用

特质

要将 doctrine-assert 添加到您的测试中,您只需在测试类中使用提供的特质即可

use DoctrineAssertTrait;

并实现一个 getEntityManager(): EntityManager 方法,以便特质可以访问您的测试实体管理器。

现在您可以使用以下断言。

断言

所有数据库断言都需要一个根实体和一个查询配置。查询配置定义了从根实体(零个或多个)开始的一组连接,然后定义用于断言的值。

例如

$this->assertDatabaseHas(
    SomeEntity::class, // <-- root entity
    [                  // <-- query config
        AnotherEntity::class => [
            YetAnotherEntity::class => [
                'active' => true
            ]
        ]
    ]
);

在这里我们可以看到,我们将 AnotherEntity::class 连接到 SomeEntity:class,然后 YetAnotherEntity::class 连接到 AnotherEntity::class,然后断言 YetAnotherEntity::class 上的 active 值在一种或多种情况下为 true

我们可以继续这种嵌套和连接,直到我们需要的程度,包括每个实体添加多个连接。

$this->assertDatabaseHas(
    SomeEntity::class,
    [
        'active' => true,
        AnotherEntity::class => [
            'active' => true,
            YetAnotherEntity::class => [
                'active' => true
                // And we could just keep going if we needed to
            ]
        ],
        FinallyAnotherEntity::class => [
            'active' => true
        ]
    ]
);

使用此功能,我们可以快速轻松地构建针对当前数据库状态的复杂断言。

数据库包含

断言数据库包含一个或多个与提供的查询配置匹配的实体。

$this->assertDatabaseHas(
    SomeEntity::class,
    [
        'active' => true
    ]
);

数据库缺少

断言数据库没有与提供的查询配置匹配的实体。

$this->assertDatabaseMissing(
    SomeEntity::class,
    [
        'active' => true
    ]
);

数据库计数

断言数据库恰好有 $count 个与提供的查询配置匹配的实体。

$this->assertDatabaseCount(
    100,  // <-- count
    SomeEntity::class,
    [
        'active' => true
    ]
);

测试

如果您想扩展 doctrine-assert 或为发现的错误创建测试用例,则您需要能够运行测试并创建新的测试。

运行测试

运行测试应该像这样简单

bash qa.bash

这将运行

如果您还想使用 Infection 运行测试,请使用

RUN_INFECTION='yes' bash qa.bash

不过,您需要安装 XDebug 才能正常工作,因为它需要生成覆盖率。

测试框架

您可以自由跳过本节,直接进入 '创建新测试'

问题

为了测试库,我们需要生成大量实体以及创建相关的数据库模式。为了使代码自包含并节省将大量测试实体提交到代码库中,我们使用虚拟文件系统 vfs://streamsqlite。这还有额外的好处,即在 RAM 中运行一切,使测试套件尽可能快速。

测试框架是如何工作的

以下过程在每个测试运行之前执行,并由 AbstractDoctrineAssertTest 管理。

虚拟文件系统

我们首先初始化虚拟文件系统(虚拟文件系统),然后复制我们将用于生成测试实体的 Doctrine YAML 映射文件。

实体管理器

现在,我们使用 YAML 映射配置和内存中的 SQLite 数据库设置实体管理器。在每个测试运行之前,数据库都会被重新创建,以确保测试之间没有泄漏。

生成实体

设置实体管理器后,我们可以使用它的元数据和 EntityGenerator 创建测试实体。在我们可以使用这些实体之前,我们还需要遍历并包含它们。

更新模式

最后,我们将数据库模式更新为与我们的实体匹配,然后我们就可以开始了。

测试结构

DoubleOneToOne
├── AssertDatabaseCountTest.php
├── AssertDatabaseHasTest.php
├── AssertDatabaseMissingTest.php
└── Vfs
    └── config
        ├── Vfs.DoubleOneToOne.One.dcm.yml
        ├── Vfs.DoubleOneToOne.Two.dcm.yml
        └── Vfs.DoubleOneToOne.Three.dcm.yml

测试根据它们要测试的实体类型进行组织,所有使用相同实体集的测试都存储在一个目录中,在这个例子中是 DoubleOneToOne。这样我们可以最小化需要定义的实体集数量。

接下来是虚拟文件系统 Vfs/,它将被此文件夹中的任何测试使用。在 Vfs/config 中,我们使用 Doctrine 的 YAML 映射格式定义测试实体。YAML 文件名应与内部定义的类名匹配,因此 Vfs\DoubleOneToOne\One 变为 Vfs.DoubleOneToOne.One,并在末尾加上 .dcm.yml,即 Vfs.DoubleOneToOne.One.dcm.yml

创建测试

以下是测试的基本轮廓。

class YourTest extends AbstractDoctrineAssertTest
{
    public const VFS_NAMESPACE = 'Vfs\\YourTest\\';

    use DoctrineAssertTrait;

    protected function getVfsPath(): string
    {
        return __DIR__ . '/Vfs';
    }

    public function setUp()
    {
        parent::setUp();

        $this->createEntities();
    }

    public function testSomethingPasses(): void
    {
        $this->assertDatabaseHas(
            self::VFS_NAMESPACE . 'One',
            [
                'test' => 'passes'
            ]
        );
    }
    
    public function testSomethingFails(): void
    {
        $this->expectException(ExpectationFailedException::class);
    
        $this->assertDatabaseHas(
            self::VFS_NAMESPACE . 'One',
            [
                'test' => 'fails'
            ]
        );
    }

    private function createEntities(): void
    {
        $generator = Factory::create();
        $populator = new Populator($generator, $this->getEntityManager());

        $populator->addEntity(self::VFS_NAMESPACE . 'One', 1,
            [
                'test' => 'passes'
            ]
        );

        // ...

        $populator->execute();
    }
}

定义实体

如果测试所需的实体尚不存在,则我们为测试创建一个目录和定义测试所需所有实体的 YAML 文件。如果实体已经存在,则我们可以简单地向该目录添加新的测试。

创建测试类

现在我们创建一个测试类。该类 必须 继承自 AbstractDoctrineAssertTest

您还希望使用 DoctrineAssertTrait,以便可以使用它进行测试断言。

创建测试方法

我们现在为每个要测试的项目创建一个方法(就像平常一样)。

设置测试数据

您可以使用 Fakers 生成器和填充器设置测试所需的测试数据。

$generator = Factory::create();
$populator = new Populator($generator, $this->getEntityManager());

$populator->addEntity(self::VFS_NAMESPACE . 'Three', 1,
    [
        'name' => 'Three'
    ]
);

// ...

$populator->execute();

进行断言

最后,您将使用 doctrine-assert 断言进行断言。如果您想测试断言是否正确失败,则可以简单地期望 ExpectationFailedException

$this->expectException(ExpectationFailedException::class);