CakePHP 3.4.2 测试 POST 的响应总是返回 NULL
CakePHP 3.4.2 Testing POST's response always returning NULL
我目前正在测试一个应用程序,该应用程序仅通过给定的 ID 搜索记录。
它工作正常,但测试拒绝 return 代码中的响应。奇怪的是它只显示在 CLI 中。
我正在使用 cakephp 提供的 phpunit:
"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:我只能通过在 "$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
}
控制器操作不应该回显数据,即使它在某些甚至大多数情况下可能有效。输出不是来自渲染视图模板的数据的正确方法是配置和 return 响应 object,或使用序列化视图。
测试环境依赖于正确执行此操作,因为它不会缓冲可能的输出,但会使用 return 从控制器操作中编辑的实际值。
以下基本是抄袭自https://whosebug.com/a/42379581/1392379
引自文档:
Controller actions generally use Controller::set()
to create a context that View uses to render the view layer. Because of the conventions that CakePHP uses, you don’t need to create and render the view manually. Instead, once a controller action has completed, CakePHP will handle rendering and delivering the View.
If for some reason you’d like to skip the default behavior, you can return a Cake\Network\Response
object from the action with the fully created response.
* 从 3.4 开始就是 \Cake\Http\Response
Cookbook > Controllers > Controller Actions
配置响应
使用 PSR-7 兼容接口
$content = json_encode($comuna);
$this->response->getBody()->write($content);
$this->response = $this->response->withType('json');
// ...
return $this->response;
PSR-7 兼容接口使用不可变方法,因此利用了 withType()
的 return 值。与设置 headers 和东西不同,通过写入现有流来更改 body 不会更改响应的状态 object.
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');
这还需要使用请求处理程序组件,并启用扩展解析和使用附加 .json
的相应 URL,或者使用 application/json
接受 header.
另见
我目前正在测试一个应用程序,该应用程序仅通过给定的 ID 搜索记录。 它工作正常,但测试拒绝 return 代码中的响应。奇怪的是它只显示在 CLI 中。
我正在使用 cakephp 提供的 phpunit:
"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:我只能通过在 "$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
}
控制器操作不应该回显数据,即使它在某些甚至大多数情况下可能有效。输出不是来自渲染视图模板的数据的正确方法是配置和 return 响应 object,或使用序列化视图。
测试环境依赖于正确执行此操作,因为它不会缓冲可能的输出,但会使用 return 从控制器操作中编辑的实际值。
以下基本是抄袭自https://whosebug.com/a/42379581/1392379
引自文档:
Controller actions generally use
Controller::set()
to create a context that View uses to render the view layer. Because of the conventions that CakePHP uses, you don’t need to create and render the view manually. Instead, once a controller action has completed, CakePHP will handle rendering and delivering the View.If for some reason you’d like to skip the default behavior, you can return a
Cake\Network\Response
object from the action with the fully created response.
* 从 3.4 开始就是 \Cake\Http\Response
Cookbook > Controllers > Controller Actions
配置响应
使用 PSR-7 兼容接口
$content = json_encode($comuna);
$this->response->getBody()->write($content);
$this->response = $this->response->withType('json');
// ...
return $this->response;
PSR-7 兼容接口使用不可变方法,因此利用了 withType()
的 return 值。与设置 headers 和东西不同,通过写入现有流来更改 body 不会更改响应的状态 object.
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');
这还需要使用请求处理程序组件,并启用扩展解析和使用附加 .json
的相应 URL,或者使用 application/json
接受 header.