Fakerの日時データ表示形式が合わないので、PHPUnitテストに失敗する - d-sazanami/laravel-jissenkaihatsu-v1 GitHub Wiki
現象
ファクトリを使ってテストデータを生成したところ、日付カラムのデータがファクトリで生成された日付とデータベース上のデータと形式が異なってしまっているため、テストが失敗した
1) Tests\Feature\ExampleTest::testBasicTest
Failed asserting that a row in the table [people] matches the attributes {
"id": 67,
"name": "Dolly Schiller",
"mail": "[email protected]",
"created_at": "2022-03-12T06:45:23.000000Z",
"updated_at": "2022-03-12T06:45:23.000000Z",
"age": 38
}.
Found similar results: [
{
"id": 67,
"name": "Dolly Schiller",
"mail": "[email protected]",
"created_at": "2022-03-12 15:45:23",
"updated_at": "2022-03-12 15:45:23",
"age": 38
}
].
前提
config/app.php
return [
'timezone' => 'Asia/Tokyo',
'locale' => 'ja',
'faker_locale' => 'en_US',
調査
$person = Person::find(rand(1, $count));
の変数を var_dump
してみる。
# vendor/bin/phpunit
PHPUnit 9.5.16 by Sebastian Bergmann and contributors.
..F 3 / 3 (100%)/var/www/html/tests/Feature/ExampleTest.php:33:
class App\Models\Person#1601 (30) {
protected $connection =>
string(7) "testing"
protected $table =>
string(6) "people"
protected $primaryKey =>
string(2) "id"
protected $keyType =>
string(3) "int"
public $incrementing =>
bool(true)
protected $with =>
array(0) {
}
protected $withCount =>
array(0) {
}
public $preventsLazyLoading =>
bool(false)
protected $perPage =>
int(15)
public $exists =>
bool(true)
public $wasRecentlyCreated =>
bool(false)
protected $escapeWhenCastingToString =>
bool(false)
protected $attributes =>
array(6) {
'id' =>
int(70)
'name' =>
string(18) "Emilio Schiller II"
'mail' =>
string(24) "[email protected]"
'created_at' =>
string(19) "2022-03-13 08:19:26"
'updated_at' =>
string(19) "2022-03-13 08:19:26"
'age' =>
int(99)
}
protected $original =>
array(6) {
'id' =>
int(70)
'name' =>
string(18) "Emilio Schiller II"
'mail' =>
string(24) "[email protected]"
'created_at' =>
string(19) "2022-03-13 08:19:26"
'updated_at' =>
string(19) "2022-03-13 08:19:26"
'age' =>
int(99)
}
protected $changes =>
array(0) {
}
protected $casts =>
array(0) {
}
protected $classCastCache =>
array(0) {
}
protected $attributeCastCache =>
array(0) {
}
protected $dates =>
array(0) {
}
protected $dateFormat =>
NULL
protected $appends =>
array(0) {
}
protected $dispatchesEvents =>
array(0) {
}
protected $observables =>
array(0) {
}
protected $relations =>
array(0) {
}
protected $touches =>
array(0) {
}
public $timestamps =>
bool(true)
protected $hidden =>
array(0) {
}
protected $visible =>
array(0) {
}
protected $fillable =>
array(0) {
}
protected $guarded =>
array(1) {
[0] =>
string(2) "id"
}
}
Array
(
[id] => 70
[name] => Emilio Schiller II
[mail] => [email protected]
[created_at] => 2022-03-12T23:19:26.000000Z
[updated_at] => 2022-03-12T23:19:26.000000Z
[age] => 99
)
Time: 00:09.594, Memory: 32.00 MB
There was 1 failure:
1) Tests\Feature\ExampleTest::testBasicTest
Failed asserting that a row in the table [people] matches the attributes {
"id": 70,
"name": "Emilio Schiller II",
"mail": "[email protected]",
"created_at": "2022-03-12T23:19:26.000000Z",
"updated_at": "2022-03-12T23:19:26.000000Z",
"age": 99
}.
Found similar results: [
{
"id": 70,
"name": "Emilio Schiller II",
"mail": "[email protected]",
"created_at": "2022-03-13 08:19:26",
"updated_at": "2022-03-13 08:19:26",
"age": 99
}
].
/var/www/html/vendor/laravel/framework/src/Illuminate/Foundation/Testing/Concerns/InteractsWithDatabase.php:29
/var/www/html/tests/Feature/ExampleTest.php:36
FAILURES!
Tests: 3, Assertions: 3, Failures: 1.
日付カラムのデータが、オブジェクトの $attributes
や $original
では、 Y-m-d H:i:s
形式だが、 Array
で toArray
後のオブジェウトを見ると、ISO-8601形式になっている。
attributesToArray
でも見てみたが、ISO-8601形式で日付が保持される。
デフォルトの日付形式のカスタマイズはできる
https://readouble.com/laravel/8.x/ja/eloquent-serialization.html にある通り、 serializeDate
メソッドを実装できれば良い。
そのまま Person
モデル・クラスにこのメソッドを書いてみたが、
になる。
Illuminate\Database\Eloquent\Model
にはじかに、serializeDate
メソッドが定義されていなかった。
vendor
ディレクトリ以下をメソッド名で検索しても、該当ファイルは見つからなかったので、よくわからなかった。
対応
日付の表示形式は、全体的に変えたいことが多いので、 https://qiita.com/kenkubomi/items/58d026733266a30e801a に習って、トレイトで実装することで、解決した。