CakePHP 3.4.2 Тестирование ответа POST, всегда возвращающего NULL
В настоящее время я тестирую приложение, которое просто ищет запись по заданному идентификатору. Работает нормально, но тестирование отказывается возвращать ответ в коде. Странно, но только в CLI.
Я использую phpunit, предоставленный cakephp:
"phpunit / phpunit": "^ 5.7 | ^ 6.0"
Вот противоречивый код:
$this->post('/comunas/findByBarrio',[
'barrio_id'=>1
]);
var_dump($this->_response->body());die(); //This is just a test which always returns NULL... while the CLI shows the actual response, which is a JSON.
Также та же проблема возникает при выполнении GET или POST для любого другого действия. Но вот код целевого контроллера:
public function findByBarrio()
{
$this->autoRender = false;
if ($this->request->is('POST'))
{
$data = $this->request->getData();
if (!empty($data['barrio_id']))
{
$this->loadModel('Comuna');
$barrio_id = $data['barrio_id'];
$comuna = $this->Comuna->find('list',['conditions' => ['barrio_id'=>$barrio_id]])
->hydrate(false)
->toArray();
if ($comuna)
{
echo json_encode($comuna);
}
else
{
throw new NotFoundException('0');
//echo 0; //Comuna no encontrada para el barrio recibido
}
}
else
{
echo -1;
}
}
}
Заранее спасибо!
ОБНОВЛЕНИЕ 1: мне удалось получить выходные данные только с помощью "ob_start()" и "ob_get_clean()" вокруг метода "$this->post". Хотелось бы, чтобы был более чистый путь...
ОБНОВЛЕНИЕ 2: Теперь это работает! Просто используя PSR-7-совместимый интерфейс. Спасибо! Вот исправленный контроллер:
public function findByBarrio()
{
$this->autoRender = false;
$this->response = $this->response->withType('json'); //CORRECTION
if ($this->request->is('POST'))
{
$data = $this->request->getData();
if (!empty($data['barrio_id']))
{
$this->loadModel('Comuna');
$barrio_id = $data['barrio_id'];
$comuna = $this->Comuna->find('list',['conditions' => ['barrio_id'=>$barrio_id]])
->hydrate(false)
->toArray();
if ($comuna)
{
$json = json_encode($comuna);
$this->response->getBody()->write($json); //CORRECTION
}
else
{
//Comuna no encontrada para el barrio recibido
$this->response->getBody()->write(0); //CORRECTION
}
}
else
{
//No se recibió el barrio
$this->response->getBody()->write(-1); //CORRECTION
}
}
return $this->response; //CORRECTION
}
1 ответ
Действия контроллера не должны отражать данные, даже если они могут работать в некоторых, может быть, даже в большинстве ситуаций. Правильный способ вывода данных, которые не основаны на визуализированном шаблоне представления, состоит в том, чтобы сконфигурировать и вернуть объект ответа или использовать сериализованные представления.
Тестовая среда полагается на выполнение этого должным образом, поскольку она не буферизирует возможные выходные данные, но будет использовать фактическое значение, возвращаемое действием контроллера.
Ниже в основном копия с /questions/47460189/kak-vyivesti-sobstvennoe-soderzhimoe-tela-http-s-cakephp-34-eho-vyizyivaet-oshibku-nevozmozhno-vyibrosit-zagolovki/47460205#47460205
Цитата из документов:
Действия контроллера обычно используют
Controller::set()
создать контекст, который View использует для визуализации слоя вида. Из-за соглашений, которые использует CakePHP, вам не нужно создавать и визуализировать представление вручную. Вместо этого после завершения действия контроллера CakePHP будет обрабатывать рендеринг и доставку представления.Если по какой-то причине вы хотите пропустить поведение по умолчанию, вы можете вернуть
Cake\Network\Response
объект от действия с полностью созданным ответом.
* Начиная с 3.4 это будет\Cake\Http\Response
Кулинарная книга> Контроллеры> Действия контроллера
Настройте ответ
Использование PSR-7-совместимого интерфейса
$content = json_encode($comuna);
$this->response->getBody()->write($content);
$this->response = $this->response->withType('json');
// ...
return $this->response;
Интерфейс, совместимый с PSR-7, использует неизменяемые методы, поэтому использование возвращаемого значения withType()
, В отличие от установки заголовков и прочего, изменение тела путем записи в существующий поток не изменяет состояние объекта ответа.
CakePHP 3.4.3 добавит неизменный withStringBody
метод, который может использоваться в качестве альтернативы записи в существующий поток.
$this->response = $this->response->withStringBody($content);
Использование устаревшего интерфейса
$content = json_encode($comuna);
$this->response->body($content);
$this->response->type('json');
// ...
return $this->response;
Используйте сериализованное представление
$content = json_encode($comuna);
$this->set('content', $content);
$this->set('_serialize', 'content');
Для этого необходимо также использовать компонент обработчика запросов, а также включить расширение анализа и использование соответствующих URL-адресов с .json
или приложить соответствующий запрос с application/json
принять заголовок.