1. 首页
  2. Laravel

Laravel通过工厂州深入工厂

我怀疑,如果您熟悉Laravel,您可能会在应用程序开发中使用模型工厂,甚至可能使用工厂状态。文档向您展示了使用工厂来播种和创建测试数据的机制,但是我想考虑一些有效地将工厂与模型结合使用的指导思想。
以下是我在更有效地使用工厂状态时考虑的一些方法:
首先,使用静态值,而不是对所有内容都使用Faker。
其次,您的工厂应该只创建创建模型实例所需的最简单属性集。使用静态数据,而不是Faker
我并不是说使用Faker是错误的,而是,静态值可以使测试数据比随机数据更明显。
考虑下面的User工厂:
1$factory->define(AppUser::class, function (Faker $faker) {2return [7];8});
代码示例是Laravel 5.6附带的用户工厂。工厂的定义和它毫无关系,我想批评它是完全正确的。但是,我想让您考虑一下,当您运行测试套件时,每次都会生成新的值:
1// First test run 2array:5 [>>>>> 8] 910// Second test run11array:5 [17]
您可能会觉得这种随机测试数据是一件好事,它使您的测试套件更加健壮。这是一个有效的论据,但是考虑一下你需要编写的验证数据的测试:
1public function testWelcomeMessageTest()2{46$response->assertSeeText(\”Welcome \”.$user->name);7}
我想再次强调,这个测试本身没有什么问题,但我觉得有额外的\”魔力\”需要在你的大脑中进行一点解析。我使用一个变量来断言测试正在通过,而不是一个硬编码的断言,它使测试在我的脑海中更具可读性。
考虑以下工厂:
1$factory->define(AppUser::class, function (Faker $faker) {2return [5// …6];7});
硬编码的名称和电子邮件是一个微妙的变化,但现在我的测试可能看起来像这样:
1public function testWelcomeMessageTest()2{3factory(\”AppUser\”)->create();46$response->assertSeeText(\”Welcome Example User\”);7}
另一种方法是使用一个拥有动态数据并覆盖您想要测试的内容的工厂:
1public function testWelcomeMessageTest()2{3factory(\”AppUser\”)->create([5]);68$response->assertSeeText(\”Welcome Example User\”);9}
您应该在应用程序中做您觉得合适的事情,但我希望您至少考虑到您不必为所有事情都使用faker。事实上,由于这种微妙的变化,您的测试可能会更加清晰。
如果您不想失去faker提供的随机性,请考虑在默认测试中使用工厂状态,其中包含一些静态值:
1$factory->define(AppUser::class, \”user\”, function (Faker $faker) {2return [5];6});
然后在您的测试中,您需要一个基本值,静态用户:
1public function testWelcomeMessageTest()2{3factory(\”AppUser\”)->states(\”user\”)->create();46$response->assertSeeText(\”Welcome Example User\”);7}
user状态表示模型所需的基本属性集它是创建模型所需的最小可行属性。最小可行属性
使用创建模型所需的最小数据量创建工厂和测试数据是在您的系统中提倡的一个好习惯测验。如果一个字段是可以为null的,或者模型有可选的关系,不要在默认工厂中定义它们。
您的测试将更容易帮助您捕获null值和空关系的问题。空模型关系通常是用户在应用程序中遇到的第一种状态。
当数据库中的某个列可以为空时,默认情况下在工厂中忽略它,然后使用状态进一步测试具有超过所需最小数据的模型。
以论坛应用程序为例。当用户第一次注册时,将不会创建任何帖子,也不会对其他人的帖子发表任何评论。它代表应用程序中最基本的用户,具有最低的要求。
拥有工厂数据和伪造者供您使用,这使得您很容易填写尽可能多的数据,但只定义默认模型工厂状态中绝对必要的数据。使用状态增强工厂数据
使用示例对于论坛应用程序,我们可以为有帖子的用户定义一个状态,如果我们的测试需要的数据超过了最低要求:
1$factory2->state(AppUser::class, \”with_posts\”, [])3->afterCreatingState(AppUser::class, \”with_posts\”, function ($user, $faker) {4factory(AppPost::class, 5)->create([6]);7});
这个状态没有任何重写数据,这样我们就可以将空数组作为第三个参数而不是闭包传递。我们使用afterCreatingState方法来定义一些与用户相关联的帖子,我们现在可以在测试中使用这些帖子:
这种方法的最大缺点是在afterCreatingState回调中硬编码5帖子。我只是在写伪代码,但是像这样的API可能很好:
2->states(\”with_posts\”,>3->create();
然后在工厂API的另一边,类似这样的东西:
1$factory2->state(AppUser::class, \”with_posts\”, [])3->afterCreatingState(AppUser::class, \”with_posts\”, function ($user, $faker, $config) {4factory(AppPost::class, $config->get(\”posts_count\”, 5))->create([6]);7});
同样,这是伪代码,不会工作!但我想展示几种方法,说明这种方法可能更好。也许这是一个包可以通过某种方式扩展基本工厂功能来实现此API的领域。
即使有缺点,我们仍然有一个很好的声明方式来使用带有post的用户状态。其他工厂状态方法我们还可以在测试框架中使用一个trait来为有帖子的用户创建一个更动态的状态,以及我们想要给用户的任何其他状态:
***17***
在需要有帖子的用户的测试中,您可以使用以下内容:
***18***
我想在顶部定义***19***,在这里我导入了trait,因为我一眼就能看出trait是用于工厂数据的。使用trait需要相当多的样板,但是比我们的静态工厂状态更灵活,posts计数硬编码为五。
learnmorep>您可以在Laravel文档中了解更多关于工厂状态的信息。如果您想更多地了解和思考工厂的工作方式,另一个优秀的资源是Ruby gem Factory Bot,特别是入门文档。
工厂应尽可能少是另一个关于使用工厂的优秀资源,作者是上述Factory Bot库的作者。

Laravel通过工厂州深入工厂 为WP2原创文章,链接:https://www.wp2.cn/laravel/laravel%e9%80%9a%e8%bf%87%e5%b7%a5%e5%8e%82%e5%b7%9e%e6%b7%b1%e5%85%a5%e5%b7%a5%e5%8e%82/