【问题标题】:Model Contracts/Interfaces in Laravel 5Laravel 5 中的模型合约/接口
【发布时间】:2017-05-25 15:21:48
【问题描述】:

在模型的工厂模拟上强加接口或契约的最 Laravel 方式是什么?

例如,假设我有一个模型Dog。我使用工厂来模拟它,并为它编写一个测试。我想确保如果我模拟一个不符合合同/接口的实例,则会引发错误。

\App\Dog.php:

class Dog extends Model
{
    protected $table = 'dogs';
    protected $fillable = ['name', 'breed' ]; // Dogs must have both of these
}

数据库/工厂/ModelFactory.php

$factory->define(App\User::class, function (Faker\Generator $faker) {
    return [
        'name' => $faker->name // no mention of breed, which is required
    ];
});

测试/DogTest.php

class RoadshowUnitTest extends TestCase
{
   /** @test **/
   public function i_should_be_able_to_make_a_dog()
   {
       $dog = factory(App\Roadshow::class, 1)->make();
       // ... internal type assertions go here
   }
}

当我运行这个测试时,我应该得到某种错误;工厂根本不应该生产Dog,因为它缺少一个重要的领域。如何对模型以及使用它的任何事物(如工厂)施加要求?

【问题讨论】:

  • 当你说它是“必需的”时,你是什么意思?数据库约束、控制器中的验证等?
  • @jackel414 如果存在不同级别的“必需”,那么在没有任何Dog 实例(如来自工厂)的情况下将“品种”注册为属性所需的任何内容都无法存在。换句话说,是创建实例所必需的。

标签: php laravel-5 interface phpunit tdd


【解决方案1】:

模型工厂只是创建您传递给它的模型对象的一个​​新实例,并将值分配给您指定的属性(在这种情况下,只是“名称”属性)。正如您可以执行$user = new User; 并实例化一个空的用户对象一样,您的工厂可以在您运行make 时拥有任意数量的属性。

为确保该模型类的持久化实例具有适当的数据属性,您可以:添加验证请求数据的验证逻辑(在自定义请求类或控制器中),或将约束应用于包含模型数据。理想情况下你会同时做。

使用make 命令与使用new Model 相同,意味着数据还没有保存到数据库中(如果你想持久化你可以在make() 之后使用save(),或者使用create()代替make())。因此,您拥有的任何数据库约束都不会发挥作用。同样,由于它不是 HTTP 请求(并且没有调用控制器方法),因此您拥有的任何验证逻辑也不会被命中。

抱歉,这有点啰嗦 - 简短的回答是模型工厂本身不会验证您的数据。

【讨论】:

  • 可以强制Model工厂实现接口吗?
  • 一个模型类绝对可以用来实现一个接口(如果你看一下 Laravel 的模型基类,你会发现它实现了许多接口)。然而,实现它的不是模型工厂——工厂只是通知类本身。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-08-08
  • 2015-05-07
  • 2016-09-11
  • 1970-01-01
  • 2013-01-08
  • 2015-10-03
  • 2015-03-12
相关资源
最近更新 更多