問題
assertDatabaseHasでテストが失敗したとき
$this->call('PATCH', '/api/users/1', ['name' => 'ほげほほげ']);
$this->assertDatabaseHas('users', ['name' => 'ふがふが']);
データベース内のマルチバイトが正しく表示されない
# There was 1 failure:
#
# 1) Tests\Feature\UsersControllerTest::testUsersUpdate
# Failed asserting that a row in the table [users] matches the attributes {
# "title": "\u3075\u304c\u3075\u304c"
# }.
#
# Found: [
# {
# "id": 1,
# "title": "\u307b\u3052\u307b\u307b\u3052",
# "created_at": "2019-09-29 09:33:59",
# "updated_at": "2019-09-29 09:33:59"
# }
# ].
結論
文字化けの原因は class InteractsWithDatabase 内で使用している json_encode
の第2引数が JSON_PRETTY_PRINT
のみになっているため。
これは、./tests/TestCase.php
で assertDatabaseHas
でオーバーライドして引数を修正できる
./tests/TestCase.php
<?php
namespace Tests;
use Illuminate\Foundation\Testing\TestCase as BaseTestCase;
abstract class TestCase extends BaseTestCase
{
use CreatesApplication;
/**
* @see github.com/laravel/framework/blob/5.8/src/Illuminate/Foundation/Testing/Concerns/InteractsWithDatabase.php#L21
*/
protected function assertDatabaseHas($table, array $data, $connection = null)
{
$this->assertThat(
$table,
new HasInDatabaseMb($this->getConnection($connection), $data)
);
return $this;
}
}
class BaseTestCase > trait InteractsWithDatabase > class HasInDatabase
のような依存で、実際の出力整形はHasInDatabase
クラスのメソッドが行っているため、json_encodeを使用しているメソッドを上書きして新しいクラス ./tests/HasInDatabaseMb.php
とする。
./tests/HasInDatabaseMb.php
<?php
namespace Tests;
use Illuminate\Foundation\Testing\Constraints\HasInDatabase;
class HasInDatabaseMb extends HasInDatabase
{
/**
* @see github.com/laravel/framework/blob/5.8/src/Illuminate/Foundation/Testing/Constraints/HasInDatabase.php#L66
*/
protected function getAdditionalInfo($table)
{
$results = $this->database->table($table)->get();
if ($results->isEmpty()) {
return 'The table is empty';
}
$description = 'Found: '.json_encode($results->take($this->show), JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
if ($results->count() > $this->show) {
$description .= sprintf(' and %s others', $results->count() - $this->show);
}
return $description;
}
/**
* @see github.com/laravel/framework/blob/5.8/src/Illuminate/Foundation/Testing/Constraints/HasInDatabase.php#L84
*/
public function toString($options = 0): string
{
return json_encode($this->data, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
}
}
上記はオリジナルのソースコードの json_encode
の第2引数を
JSON_PRETTY_PRINT
から↓
JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE
に変更を行い、それ以外は変更していない。
以上のようにして assertDatabaseHas
メソッドをオーバーライドすれば、テスト失敗時に日本語が表示されるようになる。
# Time: 1.69 seconds, Memory: 24.00 MB
#
# There was 1 failure:
#
# 1) Tests\Feature\UsersControllerTest::testUsersUpdate
# Failed asserting that a row in the table [users] matches the attributes {
# "title": "ふがふが"
# }.
#
# Found: [
# {
# "id": 1,
# "title": "ほげほほげ",
# "created_at": "2019-09-29 09:50:00",
# "updated_at": "2019-09-29 09:50:00"
# }
# ].