Бесполезное сообщение об ошибке при использовании BackedEnum и assertJson
Возможно, вам интересно, почему...
Вот интересный сценарий, с которым недавно столкнулся.
Допустим, необходимо протестировать ответ API, и его значение включает `BackedEnum`:
// app/Enums/Urgency.php
enum Urgency: string {
case LOW = 'low';
case MEDIUM = 'medium';
case HIGH = 'high';
}
// tests/Feature/ExampleTest.php
$response->assertJson([
'data' => [
'urgency' => Urgency::LOW,
],
])Этот тест завершится неудачей, потому что перечисление не соответствует строковому значению в JSON-ответе. Это легко исправить, просто добавьте `->value` к перечислению, и тест будет пройден. Ничего страшного!
Но вот тут-то и становится интересно. Посмотрите внимательно на сообщение об ошибке при неудачном завершении теста:
Unable to find JSON:
[{
"data": {
"urgency": "low"
}
}]
within response JSON:
[{
"data": {
"urgency": "low"
}
}]Оба значения совпадают! Этот пример предельно прост, поэтому странности легче заметить, но теперь представьте это в ответе с десятками ключей и значений.
Внутри метода теста Laravel `assertJson` он откладывает утверждение для `PHPUnit::assertArraySubset`. Как и ожидалось, метод PHPUnit воспринимает объект `BackedEnum` и строковое значение как разные, поэтому тест проваливается, как и должно быть.
Но когда Laravel вызывает это утверждение PHPUnit, он также передает сообщение об ошибке, чтобы показать, если утверждение завершилось неудачно. И чтобы сделать сообщение об ошибке более красиво оформленным, он форматирует ожидаемые и фактические значения с помощью `json_encode` с красивым выводом.
Когда вы `json_encode` объект `BackedEnum`, он вернет строковое значение перечисления, а не сам объект перечисления.
Таким образом, тест проваливается, но сообщение об ошибке выглядит так, как будто он должен быть пройден.