Carbon::setTestNow()
で現在時刻を固定し、Carbon::now()
で固定した値になっているかを確かめる以下のようなテストがあります。
<?php
namespace Tests\Unit;
use Carbon\Carbon;
use PHPUnit\Framework\TestCase;
class Test extends TestCase
{
public function test()
{
$now = new Carbon('2020-05-12T10:00:00+09:00');
Carbon::setTestNow($now);
self::assertSame(
$now->format('Y-m-d H:i:s'),
Carbon::now()->format('Y-m-d H:i:s')
);
}
}
つい最近まではこのコードで問題なかったのですが、最近のCarbon
では失敗してしまいます。
Failed asserting that two strings are identical.
Expected :'2020-05-12 10:00:00'
Actual :'2020-05-12 01:00:00'
原因となっているのはこちらの仕様変更です。
https://github.com/briannesbitt/Carbon/issues/2481
内容としては「setTestNow()
では時間だけを固定し、タイムゾーンは固定しない」ようにするというものです。
上記テストコードではsetTestNow()
で現在時刻を固定する時はAsia/Tokyo
でタイムゾーンを設定していますが、Carbon::now()
で現在時刻を取得する時はタイムゾーンを設定していないためCarbon
のデフォルトであるUTC
が適用され、時刻のズレが発生しています。
また、assertSame()
で比較するときはタイムゾーンの情報が失われているため、デバッグ時にも気付くのが大変です。
タイムゾーンの情報を含めた出力をすると以下のようになります。
<?php
namespace Tests\Unit;
use Carbon\Carbon;
use PHPUnit\Framework\TestCase;
class Test extends TestCase
{
public function test()
{
$now = new Carbon('2020-05-12T10:00:00+09:00');
Carbon::setTestNow($now);
dd(
$now->format('Y-m-d\TH:i:sP'),
Carbon::now()->format('Y-m-d\TH:i:sP')
);
}
}
PHPUnit 9.5.10 by Sebastian Bergmann and contributors.
"2020-05-12T10:00:00+09:00"
"2020-05-12T01:00:00+00:00"
解決策としては、Carbon::setTestNow()
で設定したタイムゾーンと同じタイムゾーンでCarbon::now()
を呼び出せばOKです。
<?php
namespace Tests\Unit;
use Carbon\Carbon;
use PHPUnit\Framework\TestCase;
class Test extends TestCase
{
public function test()
{
$now = new Carbon('2020-05-12T10:00:00+09:00');
Carbon::setTestNow($now);
self::assertSame(
$now->format('Y-m-d H:i:s'),
Carbon::now('Asia/Tokyo')->format('Y-m-d H:i:s') // タイムゾーンを揃える
);
}
}