league / factory-muffin
该包的目标是能够快速创建用于测试的对象。
Requires
- php: >=5.4.0
Requires (Dev)
- doctrine/orm: ^2.5
- illuminate/database: 5.0.* || 5.1.* || 5.5.* || ^6.0
- league/factory-muffin-faker: ^2.3
- phpunit/phpunit: ^4.8.36 || ^5.7.27 || ^6.5.14 || ^7.5.20
Suggests
- doctrine/orm: Factory Muffin supports doctrine through the repository store.
- illuminate/database: Factory Muffin supports eloquent through the model store.
- league/factory-muffin-faker: Factory Muffin is very powerful together with faker.
Replaces
- zizaco/factory-muff: v3.3.0
- dev-master / 3.3.x-dev
- v3.3.0
- v3.2.1
- v3.2.0
- v3.1.0
- v3.0.1
- v3.0.0
- v3.0.0-RC1
- v3.0.0-beta1
- 2.1.x-dev
- v2.1.1
- v2.1.0
- v2.1.0-RC1
- v2.0.2
- v2.0.1
- v2.0.0
- v2.0.0-RC4
- v2.0.0-RC3
- v2.0.0-RC2
- v2.0.0-RC1
- v1.6.4
- v1.6.3
- v1.6.2
- v1.6.1
- v1.6.0
- v1.5.2
- v1.5.1
- v1.5.0
- v1.4.2
- v1.4.1
- v1.4.0
- v1.3.0
- v1.2.0
- v1.1.0
- v1.0.0
- dev-custom-pk
This package is auto-updated.
Last update: 2024-09-17 23:20:16 UTC
README
该包的目标是能够快速创建用于测试的对象。
它基本上是一个简化用于PHP的 "factory_girl"。
安装
需要PHP 5.4+和Composer。
在您的composer.json中,只需将"league/factory-muffin": "^3.3"
添加到"require-dev"
部分。
{ "require-dev": { "league/factory-muffin": "^3.3" } }
Faker支持由Factory Muffin Faker提供。如果您想启用faker支持,则需要添加"league/factory-muffin-faker": "^2.3"
。
{ "require-dev": { "league/factory-muffin": "^3.3", "league/factory-muffin-faker": "^2.3" } }
升级
现有用户查看升级指南可能会有所帮助。
使用方法
简介
这是Factory Muffin 3.0的使用指南。在本指南中,您将看到“xyz
函数可以调用”。您应假设这些函数应该在League\FactoryMuffin\FactoryMuffin
的实例上调用;您应自行跟踪此实例,当然,您当然可以拥有多个此类类的实例,以实现最大灵活性。为了简化,许多示例中都包含了$fm
变量。当使用loadFactories
函数引入文件时,该变量实际上会可用。
模型定义
您可以使用define
函数定义模型工厂。您可以像这样调用它:$fm->define('Fully\Qualified\ModelName')->addDefinitions('foo', 'bar')
,其中foo
是您要在模型上设置的属性名称,而bar
描述了您希望如何生成该属性。您还可以一次定义多个属性,如下所示:$fm->define('Fully\Qualified\ModelName')->setDefinitions('foo', 'bar')
。请注意,这两个函数都附加到内部属性定义数组,而不是替换它。有关如何工作的更多信息,请参阅生成器部分。
您还可以为模型定义多个不同的模型定义。您可以通过在模型类名前加上您的“组”名称并跟上一个冒号来实现这一点。这将导致您按如下方式定义模型:$fm->define('myGroup:Fully\Qualified\ModelName')->addDefinitions('bar', 'baz')
。您不必在这里完全定义模型,因为我们首先会查找不带组前缀的定义,然后应用您的组定义,在需要时覆盖属性定义。请注意,如果您想使用组前缀,必须还创建一个不带组前缀的定义。
我们在测试中为您提供了这样做的一种巧妙方法。PHPUnit提供了一个setupBeforeClass
函数。在该函数中,您可以调用$fm->loadFactories(__DIR__ . '/factories');
,它将包含factories文件夹中的所有文件。在这些PHP文件中,您可以放置您的定义(调用define函数的所有代码)。
loadFactories
函数将递归遍历您指定的路径下所有子文件夹,以查找工厂文件,但会忽略隐藏文件夹(即以.开头的文件夹)。如果指定的工厂目录找不到,它将抛出League\FactoryMuffin\Exceptions\DirectoryNotFoundException
异常。
创建/实例化回调
您可以使用setCallback
函数可选地指定在模型创建/实例化时执行的回调,例如:$fm->define('MyModel')->setCallback(function ($object, $saved) {})
。我们将把您的模型实例作为回调的第一个参数传递,并将一个布尔值作为第二个参数。如果模型正被持久化到数据库(使用了create函数),则布尔值为true
;如果模型没有正在被持久化(使用了instance函数),则布尔值为false
。我们在底层使用的是isPendingOrSaved
函数。请注意,如果您指定了回调并使用了create
函数,我们将在执行回调前后尝试将您的模型保存到数据库。
生成器
可调用
可调用生成器可用于您需要更定制化解决方案的情况。从您的闭包或有效的可调用函数返回的任何内容都将被设置为属性。闭包/可调用将以与上述创建/实例化回调相同的参数调用:作为第一个参数的您的模型实例(以提供更多的灵活性来按您的意愿修改它)和一个指示模型是否被持久化到数据库的布尔值。在以下示例中,我们将介绍如何使用闭包或可调用,以及如何使用faker生成属性。
示例1
如您从本例中看到的,使用闭包生成属性的能力非常有用且灵活。我们在这里使用它来根据最初随机生成的5个词长的标题生成一个slug。
$fm->define('MyModel')->setDefinitions([ 'title' => Faker::sentence(5), 'slug' => function ($object, $saved) { $slug = preg_replace("/[^a-zA-Z0-9\/_|+ -]/", '', $object->title); $slug = strtolower(trim($slug, '-')); $slug = preg_replace("/[\/_|+ -]+/", '-', $slug); return $slug; }, ]);
示例2
这将把foo
属性设置为调用MyModel::exampleMethod($object, $saved)
返回的内容。
$fm->define('MyModel')->setDefinitions([ 'foo' => 'MyModel::exampleMethod', ]);
示例3
这是一个使用我们的faker包装器设置几个不同属性的简单示例。
use League\FactoryMuffin\Faker\Facade as Faker; $fm->define('MyModel')->setDefinitions([ 'foo' => Faker::word(), // Set the foo attribute to a random word 'name' => Faker::firstNameMale(), // Set the name attribute to a random male first name 'email' => Faker::email(), // Set the email attribute to a random email address 'body' => Faker::text(), // Set the body attribute to a random string of text 'slogan' => Faker::sentence(), // Set the slogan attribute to a random sentence ]);
示例4
这将把age
属性设置为介于20到40之间的随机数。
use League\FactoryMuffin\Faker\Facade as Faker; $fm->define('MyModel')->setDefinitions([ 'age' => Faker::numberBetween(20, 40), ]);
示例5
这将把name
属性设置为随机的女性名字。因为我们首先调用了unique
方法,所以该属性应在所有生成的模型之间是唯一的。如果生成很多模型时要小心使用,因为我们可能会用完唯一的项目。此外,请注意,调用Faker::setLocale('whatever')
将重置内部唯一列表。
use League\FactoryMuffin\Faker\Facade as Faker; $fm->define('MyModel')->addDefinition('name', Faker::unique()->firstNameFemale());
示例6
这将把profile_pic
属性设置为400x400的随机图片URL。因为我们首先调用了optional
方法,所以并非所有生成的模型都会设置图片URL;有时我们会返回null。
use League\FactoryMuffin\Faker\Facade as Faker; $fm->define('MyModel')->addDefinition('profile_pic', Faker::optional()->imageUrl(400, 400));
更多
请查看faker库本身以查看所有可用方法。在这里的文档中涵盖的太多,它们在文档中涵盖的也太多。请注意,如果您想通过我们的faker类上的公共方法调整底层faker实例,可以这样做。
工厂
工厂生成器对于设置模型之间的关系很有用。工厂生成器将返回您请求生成的模型的模型ID。
示例1
当我们创建一个Foo对象时,我们会发现Bar对象也会被生成并保存,它的ID将被分配给Foo模型的bar_id
属性。
$fm->define('Foo')->addDefinition('bar_id', 'factory|Bar'); $fm->define('Bar')->addDefinition('baz', Faker::date('Y-m-d'));
创建和播种
create
函数将创建和保存您的模型,并且也会保存使用Factory
生成器生成的任何内容。如果您想创建多个实例,请查看seed
函数,它在开始时接受一个额外的参数,即在这个过程中要生成的模型数量。seed
函数将有效地重复调用create
函数。
例如,让我们创建一个用户模型,并将其与多个位置和电子邮件模型关联起来。每个电子邮件模型也会关联多个令牌模型。
$user = $fm->create('User'); $profiles = $fm->seed(5, 'Location', ['user_id' => $user->id]); $emails = $fm->seed(100, 'Email', ['user_id' => $user->id]); foreach ($emails as $email) { $tokens = $fm->seed(50, 'Token', ['email_id' => $email->id]); }
您可能会遇到以下异常
League\FactoryMuffin\Exceptions\ModelNotFoundException
如果找不到定义的模型类,则会被抛出。League\FactoryMuffin\Exceptions\DefinitionNotFoundException
如果尝试创建模型,但之前没有为其定义模型定义,则会抛出。League\FactoryMuffin\Exceptions\SaveFailedException
如果您的模型上的保存函数返回false,则会抛出。League\FactoryMuffin\Exceptions\SaveMethodNotFoundException
如果您的模型上的保存函数不存在,则会抛出。- 在尝试创建或保存模型时,您的模型抛出的任何其他异常。
还有5个其他辅助函数可用
- 您可以调用
pending
来返回一个等待保存的所有对象的数组。 - 您可以调用
isPending
并传入一个模型实例来检查是否将保存。 - 您可以调用
saved
来返回一个包含所有已保存对象的数组。 - 您可以调用
isSaved
并传入一个模型实例来检查它是否已保存。 - 您可以调用
isPendingOrSaved
并传入一个模型实例来检查它是否将保存或已保存。
另外,如果您不想使用数据库持久性,仍然可以使用 instance
函数。
删除
您可以使用 deleteSaved
函数删除所有已保存的模型。请注意,您的已保存模型将按保存的相反顺序删除,以确保关系行为正确。
如果有一个或多个模型无法删除,在尝试删除所有已保存模型后,将引发 League\FactoryMuffin\Exceptions\DeletingFailedException
。您可以通过 getExceptions
函数访问每个底层异常,该函数将返回一个异常数组。您可能会遇到以下异常
League\FactoryMuffin\Exceptions\DeleteFailedException
如果您的模型上的删除函数返回false,则会抛出。League\FactoryMuffin\Exceptions\DeleteMethodNotFoundException
如果您的模型上的删除函数不存在,则会抛出。- 在尝试删除模型时,您的模型抛出的任何其他异常。
建议您从PHPUnit的 tearDownAfterClass
函数中调用 deleteSaved
函数,但是,如果您正在使用Laravel的 TestCase
编写测试,则应在调用 parent::tearDown
之前从 tearDown
方法中调用 deleteSaved
函数。此方法将刷新应用程序实例的绑定,Factory Muffin将无法执行其删除操作。此外,这将解绑分配的异常处理程序,您将无法通过绑定解析异常来调试测试,从而模糊了真正的异常。
实际示例
首先,我们需要创建一些定义
# tests/factories/all.php use League\FactoryMuffin\Faker\Facade as Faker; $fm->define('Message')->setDefinitions([ 'user_id' => 'factory|User', 'subject' => Faker::sentence(), 'message' => Faker::text(), 'phone_number' => Faker::randomNumber(8), 'created' => Faker::date('Ymd h:s'), 'slug' => 'Message::makeSlug', ])->setCallback(function ($object, $saved) { // we're taking advantage of the callback functionality here $object->message .= '!'; }); $fm->define('User')->setDefinitions([ 'username' => Faker::firstNameMale(), 'email' => Faker::email(), 'avatar' => Faker::imageUrl(400, 600), 'greeting' => 'RandomGreeting::get', 'four' => function() { return 2 + 2; }, ]);
然后您可以在测试中使用这些工厂
# tests/TestUserModel.php use League\FactoryMuffin\Faker\Facade as Faker; class TestUserModel extends PHPUnit_Framework_TestCase { protected static $fm; public static function setupBeforeClass() { // create a new factory muffin instance static::$fm = new FactoryMuffin(); // you can customize the save/delete methods // new FactoryMuffin(new ModelStore('save', 'delete')); // load your model definitions static::$fm->loadFactories(__DIR__.'/factories'); // you can optionally set the faker locale Faker::setLocale('en_EN'); } public function testSampleFactory() { $message = static::$fm->create('Message'); $this->assertInstanceOf('Message', $message); $this->assertInstanceOf('User', $message->user); } public static function tearDownAfterClass() { static::$fm->deleteSaved(); } }
更多信息
如果您想了解更多信息,以下资源可供您参考
- 生成的API文档可在 这里 获取。
- Philip Brown的文章 可在 这里 获取。
- 我们的 测试套件 也可能对您有所帮助。
集成
贡献
有关详细信息,请查看我们的 贡献指南。
鸣谢
工厂松饼是基于 Zizaco Zizuini 对 "Factory Muff" 的原始工作的扩展,目前由 Graham Campbell 维护。在3.0版本发布之前,Scott Robertson 也是共同维护者。还要感谢我们所有优秀的 贡献者。
安全性
如果您在此软件包中发现安全漏洞,请发送电子邮件至 [email protected] 给 Graham Campbell。所有安全漏洞都将得到及时处理。您可以在 此处 查看我们的完整安全政策。
许可证
工厂松饼遵循 MIT 许可证 (MIT)。
针对企业
作为 Tidelift 订阅的一部分提供
league/factory-muffin
的维护者以及数千个其他软件包的维护者正在与 Tidelift 合作,为构建应用程序时使用的开源依赖项提供商业支持和维护。节省时间,降低风险,并提高代码质量,同时支付您使用的确切依赖项的维护者。了解更多信息 请点击这里。