Статья будет небольшая, даже совсем короткая. Для фанатов TDD, верящих, что фреймворки делают в небесах. Пару часов ковырялась с тестом $response->assertJson()->assertJsonMissing(); при одинаковом содержании обеих скобок: Этот тест проходил. И утверждал, что нечто одновременно содержится и отсутствует в ответе апи. Собственно, всё это было нужно, чтобы проверить, верно ли мой новый scope в модели Something отбраковывает элементы.  Казалось бы: пишешь тест "в ответе содержится нечто, что там как раз должно быть". И тест проходит. Далее обращаешь логику окончанием Missing. При старых данных новый тест должен падать. А тут - не упал. В итоге выяснила, что проблема в названии. Функция assertJson() проверяет наличие в ответе апи любого массива, в том числе - с большой вложенностью. Причём это вы должны ей дать аргумент с нужным количеством квадратных скобок. А assertJsonMissing() ищет в ответе на любом уровне, избавляя вас от отслеживания квадратных скобок. Зато берёт в качестве аргумента только плоские массивы, без дополнительной вложенности. В частности, мне оказалось достаточно в скобках для assertJsonMissing() в последней строчке оставить чистую Something::first()->toArray(), убрав там ключ 'data': На самом-то деле нет, в процессе тестирования при сидировании с нуля под каждый тест несколько записей создаются практически одновременно, так что у них совпадают метки времени. И в таком виде тест на отсутствие как раз падает там, где правда должно быть отсутствие - из-за timestamps. Метки времени получаются одинаковыми у присутствующих и отсутствующих в ответе записях. Тест jsonMissing падает оттого, что часть параметра всё таки есть в ответе - там те же метки времени. Если метки времени скрыты параметрами модели $visible или $hidden, функция ->toArray() их скроет. Но и в ответе апи временных меток не будет. Если они там нужны, то более верный вариант - выбрать сегмент данных, порождаемый фабрикой как уникальный. Например, так: На уникальное поле id лучше тут не надеяться, поскольку апи, скорее всего, отдаёт данные сразу по нескольким моделям. При сидировании вы наполняете эти модели мелкими порциями данных, с похожим набором айди. Поэтому тест найдёт предположительно отсутствующий айди - просто в другой модели. По полям, заявленным как уникальные внутри модели, изредка может быть совпадение между фабриками двух разных моделей с одним ключом. Указание unique() в выражении $this->faker->unique()->name(), например, при создании поля "name" в двух разных моделях обеспечивает уникальность контента поля только внутри одной фабрики. Такое же выражение внутри другой фабрики, у другой модели, может случайно создать запись с тем же контентом. Стоит проверить тест перезапуском. В отличие от стабильного совпадения по айдишникам, тут перезапуск вылечит ситуацию. Хотя такое, конечно:)  Как вариант - создать в тестируемой модели новую запись, с выбранными вручную деталями. Фабрика не выдаёт значений вроде MyExclusiveNewField. Задать такое значение полю name - полная окончательная гарантия уникальности. О том, что это - проблема нейминга функций тестирования, пишут ещё с пятой версии ларки, с 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) могут вести к неоправданным ожиданиям от их работы.  Программист. Репетитор по математике.