Как утверждать в laravel 5.4, что каждая запись в списке имеет как минимум перечисленные атрибуты?

Я просто перемещаю приложение с laravel 5.3 на 5.4. В laravel 5.3 в моих тестах API я мог убедиться, что каждая запись в ответ имеет атрибуты со следующим кодом:

$this->json('get', '/api/course-types')
        ->seeJsonStructure([
            '*' => ['id', 'aaa', 'bbb', 'ccc', 'ddd']
        ]);

Как я могу сделать то же самое с laravel 5.4?

В Illuminate/Foundation/Testing/TestResponse


person gandra404    schedule 26.01.2017    source источник
comment
Да, его больше нет. Вы можете использовать assertJson или реплицировать код для seeJsonStructure. Чтобы было ясно, это никогда не было в черте TestResponse, а скорее в черте MakesHttpRequests.   -  person bishop    schedule 26.01.2017


Ответы (3)


Я полагаю, что вы ищете assertJson() или assertExactJson().

Из документов:

Метод assertJson преобразует данный массив в формат JSON, а затем проверяет, встречается ли фрагмент JSON в любом месте всего ответа JSON, возвращаемого приложением. Таким образом, если в ответе JSON есть другие свойства, этот тест все равно будет проходить, пока присутствует данный фрагмент.

И соответствующий код:

$response = $this->json('POST', '/user', ['name' => 'Sally']);

$response
    ->assertStatus(200)
    ->assertJson([
        'created' => true,
    ]);

assertExactJson() будет искать точное совпадение, тогда как assertJson() просто проверяет наличие ваших параметров в ответе. Надеюсь, поможет!

person camelCase    schedule 26.01.2017
comment
Я хочу проверить структуру ответа, а не содержание. Это не работает. - person gandra404; 27.01.2017

Функциональность тестирования браузера была заменена на Laravel Dusk. Первоначальная функциональность была перемещена в отдельный пакет: laravel/browser-kit-testing. .

Этот пакет обеспечивает уровень обратной совместимости для тестирования «BrowserKit» в стиле Laravel 5.3 на Laravel 5.4.

Вам нужно будет следовать инструкциям по установке и использованию этого пакета, и тогда ваши существующие тесты будут работать так же, как в версии 5.3.

person patricus    schedule 26.01.2017
comment
Не работает. Тот же тест не прошел с двумя ошибками: 1) PHPUnit_Framework_Exception: Argument #1 (No Value) of PHPUnit_Framework_Assert::assertJson() must be a string 2) Error: Call to undefined method Tests\Feature\ExampleTest::assertStatus() - person gandra404; 27.01.2017
comment
@ gandra404 Похоже, вы смешиваете два набора тестов. Тестовый класс может использовать либо новую функциональность тестирования (Laravel Dusk), либо старую функциональность тестирования (BrowserKit). seeJsonStructure() доступен только в наборе тестов BrowserKit. assertStatus() доступен только в наборе тестов Dusk. - person patricus; 27.01.2017
comment
это очень странно. Я пишу тесты для серверного приложения API. Нет визуальных интерфейсов, только конечные точки REST, и основное, что я ожидаю от одной конечной точки, это: - увидеть ответ json - проверить код состояния http - проверить, что ответы json имеют определенную структуру, и теперь мне нужно разделить их на 2 разные тесты? Если это правда, то у меня новая проблема. - person gandra404; 27.01.2017
comment
@ gandra404 По сути, если вы пытаетесь использовать старый пакет BrowserKit, посмотрите документацию по тестированию для Laravel 5.3. Если вы пытаетесь использовать новый пакет Dusk, ознакомьтесь с документацией по тестированию. Ларавель 5.4. Например, при использовании Dusk вы должны использовать новый метод assertStatus(), а при использовании BrowserKit — старый метод assertResponseStatus(). - person patricus; 27.01.2017
comment
Я не предпочитаю использовать Dusk или BrowserKit. Я только как сделать тест, который работает на laravel 5.3, чтобы перейти на laravel 5.4 и не разбивать его на разные классы? - person gandra404; 27.01.2017

Я тоже часто использую seeJsonStructure(), поэтому я собрал небольшой заменитель, чтобы поместить его в свой собственный TestCase. Надеюсь, это кому-то поможет, или кто-то может посоветовать мне лучшее решение:

Добавлено в мой TestCase:

public function seeJsonStructure(TestResponse $response = null, array $structure = null, $responseData = null)
{
    if ($response && !$responseData) {
        $responseData = $response->decodeResponseJson();
    }
    if (is_null($structure)) {
        return $response->assertJson($responseData);
    }
    foreach ($structure as $key => $value) {
        if (is_array($value) && $key === '*') {
            $this->assertInternalType('array', $responseData);
            foreach ($responseData as $responseDataItem) {
                $this->seeJsonStructure(null, $structure['*'], $responseDataItem);
            }
        } elseif (is_array($value)) {
            $this->assertArrayHasKey($key, $responseData);
            $this->seeJsonStructure(null, $structure[$key], $responseData[$key]);
        } else {
            $this->assertArrayHasKey($value, $responseData);
        }
    }
    return $this;
}

Затем мне пришлось обновить свои тесты, поэтому я передаю ответ в качестве первого аргумента при вызове этого метода. Пример для SomeTest:

$response = $this->json('POST', $url, [
    'id' => $user->id
]);

$this->seeJsonStructure($response, [
    'id', 'first_name', 'last_name', 'email'
]);

Первоначальный метод Laravel был следующим: //github.com/laravel/browser-kit-testing/blob/85f9a14a63bf5a287740002fcbc4352587f8a113/src/Concerns/MakesHttpRequests.php#L348

person Dustin    schedule 02.02.2017