是否可以在 Laravel 项目中使用自己工厂中的模型?

Posted

技术标签:

【中文标题】是否可以在 Laravel 项目中使用自己工厂中的模型?【英文标题】:Is it possible to use a model in it's own factory in a Laravel project? 【发布时间】:2018-09-14 04:03:49 【问题描述】:

我的团队正在为服务器代码使用 laravel 构建一个项目。早期我们打算使用模型来管理项目中使用的一些图像,但我们还没有来自客户端的图像。因此,我们构建了模型并使用 laravel 工厂和 faker 来创建用于测试的假图像。

一个月后(以及许多测试用例之后),我们收到了来自客户端的实际图像。我将图像添加到项目中,创建结构数据库播种器以填充数据库所需的数据,并为模型编写单元测试以确认其工作。

问题是现在一些测试失败了,因为我们用于图像模型的工厂仍然使用工厂和伪造者。我们需要使用我们从 faker 提供的虚假数据中获得的模型来查找特定文件的任何地方都失败了。

我想“好吧,我可以将工厂中的假数据换成来自实际模型的随机数据”。我现在遇到的问题是,当我尝试在工厂函数中使用实际模型时,模型类只能作为工厂提供:

我知道在幕后发生这种情况是有充分理由的,我只是想知道是否有办法绕过它。如果可以在工厂中使用实际模型,那我就不必重写 lot 的测试用例来将工厂替换为实际模型。这似乎也是一种非常方便的方法,可以对您知道将存在但还没有实际资产的项目进行功能测试。

有没有办法解决这个问题,或者我应该计划放弃并重构我的测试?

【问题讨论】:

【参考方案1】:

工厂的存在是为了使用 fake 数据按需生成模型——不一定来自伪造者,而是不代表已经存在的实体的数据。您正在尝试创建依赖于已填充真实数据的数据库的工厂,但如果您有一个包含需要测试的真实数据的数据库,那么您应该直接使用该数据。您的方法将使测试依赖于现在需要分发给所有开发人员和构建服务的真实数据。

应使用Database Seeders 使用一组固定数据填充您的数据库以进行测试。在开发开始时,您应该创建一个数据库播种器(可以使用工厂)来用假数据填充您的数据库,然后一旦您获得真实数据,您就可以添加一个额外的数据库播种器(或直接从 Laravel 外部填充数据库如有必要)。这种方法意味着您可以测试您的应用程序,而无需担心数据是否真实,并且您将继续能够按照预期使用工厂。

不幸的结论是,如果您希望测试具有弹性,您将需要重构。

如果您绝对必须使用带有真实数据的工厂,那么您可以create your own faker provider 来处理数据不存在的情况。

【讨论】:

明白了,这是有道理的。我正在使用播种机来填充数据并从大多数项目的测试中调用播种机。我想我的方法有点倒退(将工厂用于特定模型,然后用结构播种机填充的模型替换它们,而不是从使用假播种机的模型开始,然后用结构播种机替换它们)。下次很高兴知道。我已经完成了重构并且还不错,但是 def 不想在下一个项目中这样做。谢谢你的解释。【参考方案2】:

我相信如果您将类对象声明为 Faker 类在工厂声明中作为参数传递,您应该能够在工厂本身中使用它。不过我可能是错的,我相信它是这样发生的,因为工厂本身就是一个函数调用,所以使用的任何参数都需要在其 function() 调用中事先声明。

如果我没记错的话,如果你这样做:

$factory->define(App\models\AreaOfAffectMap::class, function(AOA $AOA) ...

它应该可以工作。

【讨论】:

请注意,我不知道它是否行不通,因为 faker 被初始化为单例,我在尝试自己移植工厂时遇到了很多问题。 嗯,试了一下还是失败了。看起来 AOA 的类型检查会导致问题,因为 AOA 类作为工厂传递到闭包中:/ 我尝试一起删除参数(因为实际上不需要 faker)并且我回到了原始错误.不过,这是个好建议,这是一个合乎逻辑的尝试步骤。 您是否尝试过在工厂方法调用之外声明 $map,然后将其作为值传递到内部?编辑:请注意,它可能仍然会失败,因为它需要一个工厂对象。不太确定你还能做什么。

以上是关于是否可以在 Laravel 项目中使用自己工厂中的模型?的主要内容,如果未能解决你的问题,请参考以下文章

Laravel - 向工厂创建的模型添加关系

不能在 Laravel 8 中使用遗留工厂

Laravel TDD 项目的迁移

laraver框架学习------工厂模型填充测试数据

Laravel 8 Jetstream:无法使用使用工厂和播种机播种的帐户登录

如何使用 Laravel 8 中的工厂在 tinker 中创建虚拟表数据并连接它们?