ben-rowan / doctrine-assert
基于 Doctrine2 的 PHPUnit 数据库断言集合
Requires
- php: ^7.2
- ext-json: *
- doctrine/orm: ^2.6
- phpunit/phpunit: ^7.1
- symfony/finder: ^4.0
Requires (Dev)
- ext-sqlite3: *
- fzaninotto/faker: ^1.7
- infection/infection: ^0.13.4
- mikey179/vfsstream: ^1.6
- phpmd/phpmd: @stable
- phpstan/phpstan: ^0.11.12
- symfony/yaml: ^4.0
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://stream 和 sqlite。这还有额外的好处,即在 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);