在数据库中搜索模型时,由于日期时间格式导致测试失败

时间:2018-10-17 10:53:35

标签: php laravel phpunit

自Laravel 5.6起,Eloquent Date Casting可用。
所以我有一个模型 MyModel

class MyModel extends Model {
    protected $casts = ['from' => 'date:Y-m-d', 'to' => 'date:Y-m-d'];
    protected $dates = ['from', 'to'];
}

还有工厂:

$factory->define(MyModel::class, function(Faker $faker) {
    return [
        'from' => Carbon::instance($faker->dateTime),
        'to' => Carbon::instance($faker->dateTime),
        // some more attributes
    ];
}

在单元测试中,我正在寻找 MyModel 的实例:

/** @test */
public function example() {
    $myModel = factory(MyModel::class)->create();

    $this->assertDatabaseHas('my_models', $myModel->attributesToArray());
}

这就是我得到的(摘录):

  

无法断言表[my_models]中的行与属性{
  “来自”:“ 2019-01-12”,
  “至”:“ 2019-02-13”,
  }。
  找到:[{
      “ from”:“ 2019-01-12 00:00:00”,
      “至”:“ 2019-02-13 00:00:00”,
  }]。

显然,测试失败了,因为时间被附加在数据库记录的字段中。它们的类型为date

我可以将断言更新为这样的内容...

$this->assertDatabaseHas('my_models', [
    'from' => $myModel->from->toDateTimeString(),
    'to' => $myModel->to->toDateTimeString(),
] + $myModel->attributesToArray());

...但是那离优雅很远。

我该怎么做才能使此断言成功?

1 个答案:

答案 0 :(得分:1)

我最终写了一个新的断言方法,该方法将模型的日期属性格式化为Y-m-d H:i:s以进行正确的比较:

protected function assertDatabaseHasModel(string $table, Model $model, ?string $connection = null) {
    $attributes = $model->attributesToArray();
    $reflection = new ReflectionClass($model);
    $property = $reflection->getProperty('casts');
    $property->setAccessible(true);

    collect($property->getValue($model))
        ->filter(function(string $cast) {
            return starts_with($cast, 'date:');
        })
        ->each(function(string $cast, string $field) use($model, &$attributes) {
            $attributes[$field] = $model->$field->toDateTimeString();
        });

    $this->assertDatabaseHas($table, $attributes, $connection);
}