#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 на момент написания.