leoloso / faker
Faker (fzaninotto/faker) 的 WordPress 版本 PoP 的分支,由 Brain Monkey 实现
Requires
- php: >=7.4
- brain/monkey: ^2.3.1
- fakerphp/faker: ^1.16
Requires (Dev)
- dev-master
- 1.2.0
- 1.1.0
- 1.0.0
- dev-Mock-get_object_taxonomies
- dev-Mock-wp_update_post
- dev-Filters-posts-by-search
- dev-Mock-get_post_types
- dev-Remove-general-functions
- dev-Mock-general-functions
- dev-Mock-is_user_logged_in
- dev-Mock-wp_insert_comment
- dev-Mock-`wp_insert_comment`
- dev-Mock-get_terms
- dev-Added-getCountableEntityEntries
- dev-Mock-get_posts
This package is auto-updated.
Last update: 2024-09-02 12:14:45 UTC
README
这是一个用于 Brain Faker 的分支,用于在 PoP 中使用。
--
使用 Faker 和 Brain Monkey 来提供生成假 WordPress 对象和相关函数的简单方法。
测试设置
参考 Brain Monkey 的 WordPress 设置,我们可以通过 Brain Faker 功能扩展它。
class FakerTestCase extends \PHPUnit\Framework\TestCase { use Mockery\Adapter\Phpunit\MockeryPHPUnitIntegration; /** * @var \Faker\Generator */ protected $faker; /** * @var \Brain\Faker\Providers */ protected $wpFaker; protected function setUp(): void { parent::setUp(); \Brain\Monkey\setUp(); $this->faker = \Brain\faker(); $this->wpFaker = $this->faker->wp(); } protected function tearDown(): void { \Brain\fakerReset(); \Brain\Monkey\tearDown(); parent::tearDown(); } }
除了 Brain Monkey 的常规设置外,我们在测试用例实例中存储了两个属性
$faker
是一个具有 Brain Faker 功能的 Faker 实例,基本是一个方法->wp()
$wpFaker
是一个\Brain\Faker\Providers
的实例,是 Brain Faker 提供的所有方法的入口点。
建议使用属性的 doc block,因为 IDE 将能够为所有可以调用的 Faker 和 Brain Faker 方法提供自动完成。
对于 README 的其余部分,假设此测试设置,例如,将到处使用 $this->wpFaker
,但只要通过 \Brain\faker()->wp()
获取 Faker\Providers
实例,并在每个测试结束时调用 \Brain\fakerReset
,Brain Faker 就会按预期工作。
值得注意的是,与 Brain Monkey 一样,Brain Faker 不需要 PHPUnit,这里只是为了方便使用。
可以伪造什么
所有将扩展上述基本测试用例类的测试用例类都可以使用 $this->wpFaker
来生成
WP_Post
实例,并模拟相关函数如get_post
和get_post_field
WP_User
实例,并模拟相关函数如get_userdata
、get_user_by
、user_can
等WP_Term
实例,并模拟相关函数如get_term
和get_term_by
WP_Comment
实例WP_Site
实例,并模拟相关函数如get_site
WP_Post_type
实例,并模拟相关函数如get_post_type_object
和post_type_exists
WP_Taxonomy
实例,并模拟相关函数如get_taxonomy
和taxonomy_exists
WP_Error
实例
Brain Faker 生成的实例不仅是“假的”,因为它们不是来自数据库,而且它们实际上是“模拟实例”,即它们是使用 Mockery 获取的。
快速示例
class MyPostCase extends FakerTestCase { public function testPostsCanBeFaked() { $posts = $this->wpFaker->posts(10); static::assertIsArray($posts); static::assertCount(10, $posts); foreach ($posts as $post) { static::assertInstanceOf(\WP_Post::class, $post); static::assertGreaterThanOrEqual(1, $post->ID); static::assertIsString($post->post_title)); static::assertIsString($post->post_content)); static::assertIsArray($post->to_array()); } } }
$this->wpFaker->posts()
,我们用来生成假 WP_Post
实例的方法,接受第一个参数为要生成的文章数量。
第二个可选参数可以用来固定生成文章的一些属性,例如以下代码
$this->wpFaker->posts(10, ['type' => 'page', 'status' => 'publish']);
可以用来获取10篇文章,所有文章类型为“页面”,状态为“发布”。
如果没有提供,所有属性都将随机生成。
除了$this->wpFaker->posts()
外,Brain Faker还提供了$this->wpFaker->post()
,该方法返回一个模拟的WP_Post
实例,和posts()
一样,也可以接受一个可选参数数组,将属性分配给它。
之前已经提到,$this->wpFaker->posts()
接受的第一个参数是我们想要生成的对象数量。
然而,这并非必须提供,如果没有提供,Brain Faker将生成一个随机数量的对象(可能是零)。
值得注意的是,调用$this->wpFaker->posts()
(不带参数)与调用$this->wpFaker->posts
相同,这在Faker中通常是这样发生的。
有时可能希望生成一个最小或最大数量的对象,为此Brain Faker提供了两种格式的方法
$this->wpFaker->atLeast{$n}Posts()
,例如$this->wpFaker->atLeast6Posts()
$this->wpFaker->atMost{$n}Posts()
,例如$this->wpFaker->atMost20Posts()
请注意,只有当数字在1到5之间时,才可以用文字拼写它们,因此以下都是有效的方法
$this->wpFaker->atLeastOnePost()
$this->wpFaker->atMostTwoPost()
$this->wpFaker->atLeastThreePosts()
$this->wpFaker->atMostFourPosts()
$this->wpFaker->atLeastFivePosts()
还要注意,当数字为One
(或1
)时,实体可以是单数(例如,Post
而不是Posts
)。
为了设置生成的实例的最小和最大数量,Brain Faker提供了一组格式的方法
$this->wpFaker->between{$min}And{$max}Posts()
例如
$this->wpFaker->betweenOneAndThreePosts()
$this->wpFaker->between6And10Posts()
$this->wpFaker->between0AndFourPosts()
所有这些“动态命名”的方法都接受一个可选参数数组,该数组包含要分配给生成的帖子的属性
$posts = $this->wpFaker->atLeastTwoPosts(['type' => 'post']); $pages = $this->wpFaker->betweenThreeAnd10Posts(['type' => 'page']);
不仅仅是帖子
所有上面提到的关于帖子的内容也适用于其他支持的对象,实际上Brain Faker的方法列表包括
对于posts
$this->wpFaker->posts()
$this->wpFaker->atLeast{$n}Posts()
$this->wpFaker->atMosts{$n}Posts()
$this->wpFaker->between{$min}and{$max}Posts()
$this->wpFaker->post()
对于users
$this->wpFaker->users()
$this->wpFaker->atLeast{$n}Users()
$this->wpFaker->atMosts{$n}Users()
$this->wpFaker->between{$min}and{$max}Users()
$this->wpFaker->user()
对于terms
$this->wpFaker->terms()
$this->wpFaker->atLeast{$n}terms()
$this->wpFaker->atMosts{$n}terms()
$this->wpFaker->between{$min}and{$max}Terms()
$this->wpFaker->term()
对于comments
$this->wpFaker->comments()
$this->wpFaker->atLeast{$n}comments()
$this->wpFaker->atMosts{$n}comments()
$this->wpFaker->between{$min}and{$max}Comments()
$this->wpFaker->comment()
对于sites
$this->wpFaker->sites()
$this->wpFaker->atLeast{$n}sites()
$this->wpFaker->atMosts{$n}sites()
$this->wpFaker->between{$min}and{$max}Sites()
$this->wpFaker->site()
对于post types
$this->wpFaker->postTypes()
$this->wpFaker->atLeast{$n}PostTypes()
$this->wpFaker->atMosts{$n}PostTypes()
$this->wpFaker->between{$min}and{$max}PostTypes()
$this->wpFaker->postType()
对于taxonomy
$this->wpFaker->taxonomies()
$this->wpFaker->atLeast{$n}Taxonomies()
$this->wpFaker->atMosts{$n}Taxonomies()
$this->wpFaker->between{$min}and{$max}Taxonomies()
$this->wpFaker->taxonomy()
对于WP_Error
$this->wpFaker->errors()
$this->wpFaker->atLeast{$n}Errors()
$this->wpFaker->atMosts{$n}Errors()
$this->wpFaker->between{$min}and{$max}Errors()
$this->wpFaker->error()
关于返回的实例
对于所有返回的对象,Brain Faker都设置了所有真实WordPress对象所具有的公共属性。
感谢Faker,所有属性都将具有随机但“真实”的值(电子邮件将是电子邮件,URL将是URL,密码将是密码等)。
在WordPress对象中不存在但在WordPress通过魔术方法__get
提供的属性,在伪造对象上也是可用的,例如进行$this->wpFaker->user->user_login
是完美的,即使user_login
是真实WP_User
实例通过魔术方法提供的属性。
已经提到,返回的实例是通过Mockery获得的模拟对象。
重要的是要说明,这些实例上并非所有方法都被模拟。
例如,对于帖子,只有WP_Post::to_array()
方法被模拟,但其他方法如WP_Post::filter()
没有被模拟,但当然可以“手动”模拟。
例如,以下代码是有效的
$this->wpFaker->post ->shouldReceive('filter') ->once();
Brain Faker模拟的方法会因对象而异。
此外,Brain Faker还模拟了一些WordPress“相关函数”。
下面是Brain Faker为它支持的每种对象模拟的方法和函数的完整列表。
模拟的内容
帖子模拟的内容
创建伪造的WP_Post
对象时,Brain Faker创建具有以下内容的模拟
- 所有
WP_Post
对象的属性,包括WordPress通过__get
提供的属性,例如page_template
; WP_Post::to_array()
方法,其工作方式与WordPress版本完全相同;get_post
函数;get_post_field
函数;
例如
class MyPostCase extends FakerTestCase { public function testGetPostCanBeFaked() { $this->wpFaker->post(['id' => 42, 'title' => 'The Answer']); static::assertSame('The Answer', get_post(42)->post_title); static::assertFalse(get_post(1)); static::assertIsString(get_post_field('post_content', 42)); } }
当使用伪造帖子的ID调用时(因为我们知道它是通过提供的数组强制执行的),get_post
返回我们生成的伪造帖子。
然而,当使用另一个ID调用时,它返回false
,就像WordPress对于未找到的帖子所做的那样。
模拟的get_post
版本将能够识别在测试中(或在任何情况下在调用Brain\fakerReset()
之前)创建的所有帖子,并将它们正确解析,对于未创建的帖子返回false
。
请注意,get_post
返回的对象与伪造的对象完全可比,但它不是同一个实例,即严格的相等比较(===
)会失败。
对于get_post_field
也是如此,Brain Faker模拟的所有其他函数也以类似的方式工作。
用户模拟的内容
创建伪造的WP_User
对象时,Brain Faker创建具有以下内容的模拟
- 所有
WP_User
对象的属性,包括WordPress通过__get
提供的许多属性,例如first_name
、last_name
、user_login
等; WP_User::to_array()
方法;WP_User::exists()
方法;WP_User::get_site_id()
方法;WP_User::has_cap()
方法;get_user_data()
函数get_user_by()
函数user_can()
函数
此外,伪造的WP_User
实例是Brain Faker创建的唯一具有额外方法的伪造对象,该方法WordPress对象没有,即__monkeyMakeCurrent()
。
当调用时,__monkeyMakeCurrent()
还将模拟以下函数
get_current_user_id
,它将返回调用__monkeyMakeCurrent()
的实例的IDwp_get_current_user
,它将返回调用__monkeyMakeCurrent()
的实例current_user_can
,它将调用(模拟的)has_cap
方法调用__monkeyMakeCurrent()
的实例
这是非常强大的,因为只需要一行代码就可以模拟大量的WordPress代码而无需加载WordPress。
此外,考虑到伪造的 WP_User
实例以非常类似于真实 WordPress 对象的方式模拟(这适用于所有伪造对象),例如角色和能力将非常“真实”。
例如,考虑以下代码
class MyUserCase extends FakerTestCase { public function testCurrentUserCanBeFaked() { $this->wpFaker->user(['role' => 'editor'])->__monkeyMakeCurrent(); static::assertTrue(current_user_can('edit_others_pages')); } }
术语的模拟内容
在创建伪造的 WP_Term
对象时,Brain Faker 创建具有以下特性的模拟:
- 所有
WP_Term
对象的属性; WP_Term::to_array()
方法;get_term
函数,但仅在传递的参数与生成的实例匹配时调用;get_term_by
函数,但仅在传递的参数与生成的实例匹配时调用;
评论的模拟内容
在创建伪造的 WP_Comment
对象时,Brain Faker 创建具有以下特性的模拟:
- 所有
WP_Comment
对象的属性; WP_Term::to_array()
方法;
站点的模拟内容
在创建伪造的 WP_Site
对象时,Brain Faker 创建具有以下特性的模拟:
- 所有
WP_Site
对象的属性,包括 WordPress 通过__get
提供的属性; WP_Site::to_array()
方法;get_site()
函数,但仅在传递的 IDs 与生成的实例匹配时调用;
分类的模拟内容
在创建伪造的 WP_Taxonomy
对象时,Brain Faker 创建具有以下特性的模拟:
- 所有
WP_Taxonomy
对象的属性; get_taxonomy()
函数taxonomy_exists()
函数
类型的模拟内容
在创建伪造的 WP_Post_Type
对象时,Brain Faker 创建具有以下特性的模拟:
- 所有
WP_Post_Type
对象的属性; get_post_type_object()
函数post_type_exists()
函数
错误的模拟内容
在创建伪造的 WP_Error
对象时,Brain Faker 创建具有以下特性的模拟:
- 所有
WP_Error
对象的属性,但值为空; - 所有
WP_Error
公共方法;
伪造的 WP_Error
实例是 Brain Faker 创建的唯一一个属性不是“随机填充”的模拟对象,而是完全模拟的,因此可以用作 WordPress 对象。
想象一些类似以下的 WordPress 代码
function maybeAddError(\WP_Error $error): \WP_Error { if (is_error_there()) { $error->add('code', 'A message', 'some data'); } return $error; }
使用 Brain Faker(以及 Brain Monkey)我们可以这样进行测试
class MyErrorCase extends FakerTestCase { /** * Test that error have expected message and data * when `is_error_there` returns true */ public function testMaybeAddErrorWhenErrorIsThere() { \Brain\Monkey\Functions\when('is_error_there')->justReturn(true); $error = maybeAddError($this->wpFaker->error); static::assertTrue($error->has_errors()); static::assertSame('A message', $error->get_error_message()); static::assertSame('some data', $error->get_error_data()); } /** * Test that error is empty when `is_error_there` returns false */ public function testMaybeAddErrorWhenErrorIsNotThere() { \Brain\Monkey\Functions\when('is_error_there')->justReturn(false); $error = maybeAddError($this->wpFaker->error); static::assertFalse($error->has_errors()); static::assertSame([], $error->get_error_messages()); } }
请注意,即使所有 \WP_Error
方法都已模拟,测试中仍然可以覆盖已模拟的方法(这对于 Brain Faker 生成的所有伪造对象都适用)。
高级主题
关于 ID 的唯一性
对于支持 ID 的对象(帖子、用户、术语、评论),除非在选项数组中给出,否则将随机生成一个 ID。
值得注意的是,这些随机生成的 ID 在每个测试中都是 唯一的(或者至少在调用 Brain\fakerReset
之前是这样的)。对于用户,除了 ID 之外,随机生成时电子邮件和登录名也是唯一的。
例如,执行 $this->wpFaker->atLeast50Users()
时,Brain Faker 将创建至少 50 个模拟的用户实例,每个实例具有不同的 ID、电子邮件和用户登录名。
此功能基于 Faker unique()
修改器。
如 Faker 文档所述,唯一生成器可以被“重置”。在使用 Brain Faker 时,可以通过调用 $this->wpFaker->__resetUnique()
来执行此操作。
请注意,手动调用 __resetUnique()
(当调用 Brain\fakerReset
时会自动调用)可能会与 Brain Monkey 的模拟函数冲突,因此除非确切知道自己在做什么,否则应避免使用。
本地化 Faker
要获取 Faker 的本地化版本,在使用 Brain Faker 时,可以将所需的区域设置传递给 \Brain\faker()
函数。
例如
protected function setUp(): void { parent::setUp(); \Brain\Monkey\setUp(); $this->faker = \Brain\faker('fr_FR'); $this->wpFaker = $this->wpFaker->wp(); }
当然,可以为不同的区域设置拥有多个 Faker(以及 Brain Faker)实例,并在 setUp
中不实例化它们,而是在各个测试中实例化。
即使在那种情况下,在测试结束时调用一次\Brain\fakerReset()
也是可以的。
覆盖 Brain Faker 方法和函数
Brain Faker 模拟生成对象的所有方法都可以轻松覆盖。
例如
class MyUserCase extends FakerTestCase { public function testUserCanBeMadeNotExistent() { $user = $this->wpFaker->user(['id' => 123]); $user->shouldReceive('exist')->once()->andReturn(false); static::assertFalse($user->exists()); } }
在上面的例子中,生成的用户已经有一个模拟的exist
方法,该方法将返回true,因为ID大于零。
然而,我们能够覆盖方法期望并使其返回false。
这是返回实例实际上是模拟对象的事实的一个巨大优势。
遗憾的是,由于底层 Brain Monkey 的限制,此方法不能用于 Brain Faker 模拟的函数。
例如
class MyUserCase extends FakerTestCase { public function testBrainMonkeyFunctionsExpectIsIgnored() { $this->wpFaker->user(['id' => 123]); Brain\Monkey\Functions\expect('get_userdata') ->with(123) ->andReturn(false); static::assertSame(123, get_userdata(123)->ID); } }
上面的代码片段显示了如何忽略使用 Brain Monkey 的“手动”模拟get_userdata
,因此当调用它的ID时,get_userdata
仍然返回模拟的用户。
为了克服这个问题,Brain Faker 提供了一个方法 $this->wpFaker->__monkeyFunction()
,可以用来替换 Brain Faker 模拟的函数的期望。
上面的测试可以重写如下
class MyUserCase extends FakerTestCase { public function testGetUserDataCanBeOverridden() { $this->wpFaker->user(['id' => 123]); $this->wpFaker->__monkeyFunction('get_userdata') ->with(123) ->andReturn(false); static::assertFalse(get_userdata(123)); } }
需要注意的是,__monkeyFunction
必须在创建模拟对象之后调用。
这似乎假设,当使用 Brain Faker 时,应该记住所有它模拟的函数,因此应该使用$this->wpFaker->__monkeyFunction()
而不是Brain\Monkey\Functions\expect
来模拟它们。
这不是真的。
$this->wpFaker->__monkeyFunction()
始终可以用作Brain\Monkey\Functions\expect
的替代品,实际上,当与尚未被 Brain Faker 模拟的函数一起使用时,它将作为Brain\Monkey\Functions\expect
的别名,因此当在测试中使用 Brain Faker 模拟函数时,使用$this->wpFaker->__monkeyFunction()
可能是一个好主意。
安装、要求、许可
Brain Faker 在 MIT 许可下发布。
它需要 PHP 7.1+。
可以通过 Composer 安装,在 packagist.org 上作为 brain/faker
提供。
通过 Composer 它需要
fzaninotto/Faker
(MIT)brain/monkey
(MIT)mockery/mockery
(BSD-3-Clause) - Brain Monkey 所需antecedent/patchwork
(MIT) - Brain Monkey 所需