Illuminate Http Response — атрибут «оригинал» содержит строку вместо объекта просмотра

#php #unit-testing #laravel-5.2 #httpresponse

#php #модульное тестирование #laravel-5 #httpresponse

Вопрос:

Я возвращаю представление из метода контроллера следующим образом:

 return view('Main::pages.content-page', compact('content'));
  

Однако, когда я создаю объект ответа, я вижу, что атрибут «original» объекта ответа является строкой, тогда как он должен был быть объектом просмотра.

 Response {#385 ▼
     original: """
    <!DOCTYPE html>n
    <html lang="en">n
        <head>n
        <meta charset="utf-8">n
        <meta http-equiv="X-UA-Compatible" content="IE=edge">n
        <meta name="viewport" content="width=device-width, initial-scale=1">n
        <meta name="author" content="">n
        <meta name="csrf-token" content="2CQirHnZ7isCBRfkhOYkzPAWOzNIqJISrbb1mfDv">n
        <meta name="description" content="">n
        <meta name="keywords" content="">n
          <title id="page_title">    Damp;eacute;couvrirn </title>n
        .........
  

Является ли это ожидаемым поведением, потому что мои тесты на самом деле терпят неудачу из-за этого, поскольку в моем тесте я, по сути, делаю

 $this->get(route('main.page', ['content' => $content->slug]))
     ->assertResponseOk()
     ->assertViewHas('content', $content);
  

Я получаю следующий сбой

 F                                                                   1 / 1 (100%)

Time: 179 ms, Memory: 20.00MB

There was 1 failure:

1) IndexControllerTest::testGetPageMethod
The response was not a view.
Failed asserting that false is true.
  

Глядя на структуру assertViewHas() метода, мы можем понять, почему

 /**
 * Assert that the response view has a given piece of bound data.
 *
 * @param  string|array  $key
 * @param  mixed  $value
 * @return $this
 */
public function assertViewHas($key, $value = null)
{
    if (is_array($key)) {
        return $this->assertViewHasAll($key);
    }

    if (! isset($this->response->original) || ! $this->response->original instanceof View) {
        return PHPUnit::assertTrue(false, 'The response was not a view.');
    }
    ......
  

Условие ! $this->response->original instanceof View не выполняется, потому что оригинал является строкой, но должен был быть объектом просмотра.

Так что я здесь потерялся. Это ожидаемое поведение, если да, то почему условие в методе assertViewHas ?

 I am on Laravel Homestead version '3.0.2'
Laravel 5.2.45
  

Комментарии:

1. View реализует __toString() . Я не знаю, является ли это причиной, но стоит проверить, использует ли Laravel представление в строковом контексте, который вызывает это.

2. реализует __toString() как способ преобразования представления в строку. По умолчанию это объект просмотра. Вы должны убедиться, что ваш вид правильно шаблонизирован как шаблон блейда

3. Да, View реализует __toString(), но объект ответа должен только преобразовывать представление в string и устанавливать для него атрибут «content», атрибут «original» объекта ответа всегда должен быть исходным объектом представления.

Ответ №1:

Я столкнулся с этой же проблемой. В моем случае оказалось, что ответ получал объект просмотра, когда он был подготовлен, но один из классов промежуточного программного обеспечения «после», который касался ответа до его возврата, преобразовывал объект просмотра в строку.

Вы genealabs/laravel-caffeine случайно используете пакет? Именно это промежуточное программное обеспечение вызвало мою проблему. Настроив этот пакет так, чтобы он не был зарегистрирован в среде тестирования, я смог решить проблему.

Ответ №2:

Я столкнулся с той же проблемой. Я мог бы заставить ответ возвращаться как a View , когда я удалил @if / @endif -предложение из моего шаблона блейда.

Подобно ответу Райана Дарема, проблема заключалась в пакете промежуточного программного обеспечения и для меня.

Попробуйте подумать о том, какое промежуточное программное обеспечение у вас может быть запущено, скорее всего, введенное зависимостями. В моем случае это было beyondcode/laravel-query-detector . Поиск нарушающего промежуточного программного обеспечения может потребовать некоторого поиска и проб и ошибок. Если есть простой способ найти все активное промежуточное программное обеспечение «в пути», я хотел бы знать!

Решение состоит в том, чтобы найти нарушающий класс промежуточного программного обеспечения и добавить следующее к setUp методу вашего TestCase класса, чтобы он выглядел так:

 protected function setUp(): void
{
    parent::setUp();

    $this->withoutMiddleware([OffendingMiddleware::class]);

    // …
}
  

Это предотвращает загрузку промежуточного программного обеспечения в любом тестовом примере, расширяющем ваш TestCase класс, который должен быть всеми из них.

Этот ответ по-прежнему актуален для Laravel 9 на момент написания.