Маленький баг в тестировании на Laravel
Статья будет небольшая, даже совсем короткая. Для фанатов TDD, верящих, что фреймворки делают в небесах.
Пару часов ковырялась с тестом $response→assertJson ()→assertJsonMissing (); при одинаковом содержании обеих скобок:
$response
->assertJson(['data' => [Something::first->toArray()]])
->assertJsonMissing(['data' => [Something::first()->toArray()]]);
Этот тест проходил. И утверждал, что нечто одновременно содержится и отсутствует в ответе апи.
Собственно, всё это нужно было, чтобы проверить, верно ли мой новый scope в модели Something отбраковывает элементы.
Казалось бы: пишешь тест «в ответе содержится нечто, что там как раз должно быть». И тест проходит. Далее обращаешь логику окончанием Missing. При старых данных новый тест должен падать.
А тут — не упал.
В итоге выяснила, что проблема в названии. Функция assertJson () проверяет наличие в ответе апи любого массива, в том числе — с большой вложенностью. Причём это вы должны ей дать аргумент с нужным количеством квадратных скобок.
А assertJsonMissing () ищет в ответе на любом уровне, избавляя вас от отслеживания квадратных скобок. Зато берёт в качестве аргумента только плоские массивы, без дополнительной вложенности. В частности, мне оказалось достаточно в скобках для assertJsonMissing () в последней строчке оставить чистую Something: first ()→toArray (), убрав там ключ 'data':
$response->assertJsonMissing(Something::first()->toArray());
О том, что это — проблема нейминга функций тестирования, пишут ещё с пятой версии ларки, с 2017: https://github.com/laravel/framework/issues/20431 . В частности, есть комментарий о том, что assertJsonMissing — это обратная не для assertJson, а для assertJsonFragment.
Там же есть ссылка на https://laravel.com/docs/8.x/http-tests#fluent-json-testing для тестирования на отсутствие в джейсоне атрибута… то есть, собственно, снова плоский вариант тестирования.
ЗЫ решила вам написать об этом, поскольку мне тема стоила пары нервных часов. Очень нервных. От обращённого — на словах — утверждения ожидаешь и поведения обращённого. При одинаковых данных из них проходить должен ровно один.
Но нейминг функций фреймворка — это тяжёлый труд. И закрепившиеся на сегодня названия функций (как минимум, у available assertions для тестирования в Laravel) могут вести к неоправданным ожиданиям от их работы.