makeabledk/laravel-factory-enhanced

v6.0.0 2024-09-27 14:21 UTC

README

Laravel Factory Enhanced - Supercharge your tests

Laravel Factory Enhanced 🔥

Latest Version on Packagist Build Status StyleCI

将eloquent关系的魔力带入Laravel Factory。

传统上,如果你想创建一个团队并添加一些用户,你需要手动创建团队和用户,然后再次将它们关联起来。这很容易导致非常冗长的测试。

Laravel 7.x及更早版本

$team = factory(Team::class)->create();
$users = factory(User::class)->times(2)->create();
foreach ($users as $user) {
    factory(TeamMember::class)->create([
        'team_id' => $team,
        'user_id' => $user,
        'role' => 'admin'
    ]);
}

Laravel 8.0及以后版本

$team = Team::factory()
    ->hasAttached(
        User::factory()->count(2),
        ['active' => true]
    )
    ->create();

Laravel Factory Enhanced

$team = Team::factory()
    ->with(2, 'users', ['pivot.role' => 'admin'])
    ->create();

安装

您可以通过composer安装此包

composer require makeabledk/laravel-factory-enhanced

版本

Laravel 8+ 类式工厂

本包的版本4及以后与Laravel 8引入的新类式语法兼容。

Laravel 7之前的工厂

本包的版本3及更早与传统的$factory->define()语法兼容。请在此处查看文档 v3文档

升级到v4的指南

升级到本包的v4版本所需的大部分重构工作在于重写工厂以与Laravel类式工厂兼容。

如果您在升级到Laravel 8时使用Laravel Shift,许多这项工作将自动完成,您将很快走上正轨。

重写为类式工厂

请使用Laravel Shift升级Laravel版本,或参考官方文档了解如何使用类式方法编写工厂。

应用状态

在您的测试套件中将所有->state('some-state')的出现替换为->someState()

预设

本包引入的预设概念现在可以简单地重写为状态。

因此,在您的测试套件中将所有->preset('some-preset')的出现替换为->somePreset()

Times方法

在您的测试套件中将所有->times(x)的出现替换为->count(x)

工厂辅助语法

此更改完全可选。如果您愿意,可以将您的测试套件中所有出现factory(SomeModel::class)的地方更改为SomeModel::factory()

如果您选择这样做,请记住在所有模型中添加use \Makeable\LaravelFactory\Factory;

其他重大变更

已从Factory实例中删除了odds()方法。

使用方法

安装包后,您的工厂应扩展Makeable\LaravelFactory\Factory,而不是原生的Laravel Factory类。

此外,请确保在您的模型上使用相应的Makeable\LaravelFactory\HasFactory特质。

例如

app/Models/User.php

<?php

namespace App\Models;

use Makeable\LaravelFactory\HasFactory;

class User 
{
    use HasFactory;
    
    // ...
}

database/factories/UserFactory.php

<?php

namespace Database\Factories;

use Makeable\LaravelFactory\Factory;

class UserFactory extends Factory
{
    public function definition()
    {
        return [
            // ...
        ];
    }
}

现在您可以使用您熟悉的Laravel所有原生功能,以及本包提供的附加功能。

如果您不熟悉Laravel工厂,请参阅官方文档:https://laravel.net.cn/docs/master/database-testing

简单关系

您可以使用增强的工厂创建模型上定义的任何其他关系。

示例:一个具有sites()关系(多对多)的Server模型

Server::factory()->with(3, 'sites')->create();

请注意,您仍然可以使用您熟悉的任何本地功能,例如状态和属性

Server::factory()->online()->with(3, 'sites')->create([
    'name' => 'production-1'
]);

多重关系

您可以在同一工厂上指定多个关系。

鉴于我们之前的 Server 模型还有一个名为 team 的关系(属于),您可以这样做

Server::factory()
    ->with('team')
    ->with(3, 'sites')
    ->create();

现在您将有一个 1 team,它拥有 1 server,该 server 又有 3 sites

嵌套关系

接下来是更高级的使用场景,您还可以进行嵌套关系。

例如,我们可以使用嵌套重写之前的示例

Team::factory()
    ->with(3, 'servers.sites')
    ->create();

请注意,计数 '3' 适用于 最终关系,在这种情况下 sites

如果您想要 2 个服务器,每个服务器都有 3 个站点,您可以写成以下格式

Team::factory()    
    ->with(2, 'servers')
    ->with(3, 'servers.sites')
    ->create();

关系中的状态

就像您可以在因子模型上指定预定义的状态(见官方文档)一样,您也可以将完全相同的状态应用于关系。

Team::factory()    
    ->with(2, 'online', 'servers')
    ->create();

您可能会发现自己想要一个处于多个状态的关系。在这种情况下,您可以使用 andWith 方法。

Team::factory()    
    ->with(2, 'online', 'servers')
    ->andWith(1, 'offline', 'servers')
    ->create();

通过使用 andWith,我们将创建一个 '清晰的分割点',这样任何对 with 的后续调用都不会干扰 andWith 之前指定的关系。

在上面的示例中,任何进一步的关系嵌套都将应用于 '离线' 服务器。

Team::factory()    
    ->with(2, 'online', 'servers')
    ->andWith(1, 'offline', 'servers')
    ->with(3, 'servers.sites')
    ->create();

上面的示例将创建 1 个团队,该团队拥有

  • 2 个在线服务器
  • 1 个离线服务器,有 3 个站点

在关系中填充属性

您可以通过将它们作为参数传递给 with 方法来在关系上填充属性。

factory(Team::class)    
    ->with(2, 'servers', ['name' => 'laravel.com'])
    ->create();

如果关系是 belongs-to-many 关系,您还可以通过在属性名称前加上 pivot. 来填充关联模型上的属性。

Team::factory()    
    ->with(2, 'users', ['pivot.role' => 'admin'])
    ->create();

使用 apply()

所有上述使用 with 方法配置关系的示例也可以应用于基本模型,使用 apply 方法。

例如

Server::factory()
    ->apply(2, 'online', ['name' => 'laravel.com'])
    ->with(3, 'mysql', 'databases')
    ->create();

这将创建 2 个在线服务器,每个服务器都有 3 个 mysql 数据库。

事实上,通过使用本包的 HasFactory 特性,您甚至可以将这些参数传递给 ::factory() 方法本身

Server::factory(2, 'online', ['name' => 'laravel.com'])
    ->with(3, 'mysql', 'databases')
    ->create();

使用闭包进行自定义

除了直接将 countstate 传递给 with 函数外,您还可以传递一个闭包,该闭包将直接接收 FactoryBuilder 实例。

在闭包中,您可以执行在 FactoryBuilder 上所做的所有操作,包括如果您愿意,还可以进一步嵌套关系。

Team::factory()    
    ->with('servers', fn (ServerFactory $servers) => $servers
        ->count(2)
        ->active()
        ->with(3, 'sites')
    )
    ->create();

没有定义工厂的因子模型

传统上,在没有任何定义的工厂的模型上尝试使用 Model::factory() 会抛出异常。不再是这样了!

安装此包后,您完全可以使用静态的 Model::factory() 方法在任意使用 Makeable\LaravelFactory\HasFactory 特性的 Eloquent 模型上。

此外,此包还恢复了古老的 factory(Model::class) 辅助函数,您可以在任何模型上使用它,无论该模型是否有定义的工厂或使用 HasFactory 特性。

示例

factory(2, Server::class)->with(1, 'sites')->create();

可用方法

这些是在 Factory 实例上提供的额外方法,除了核心方法。

  • apply
  • fill
  • fillPivot(仅适用于 BelongsToMany
  • pipe
  • tap
  • with
  • andWith

测试

您可以使用以下命令运行测试

composer test

贡献

我们很高兴接受额外的功能拉取请求。请参阅CONTRIBUTING 以获取详细信息。

致谢

许可证

署名-相同方式共享 4.0 国际。有关更多信息,请参阅许可证文件