CakePHP 3.4.2 测试 POST 的响应总是返回 NULL [英] CakePHP 3.4.2 Testing POST's response always returning NULL

查看:17
本文介绍了CakePHP 3.4.2 测试 POST 的响应总是返回 NULL的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前正在测试一个应用程序,该应用程序仅通过给定的 id 搜索记录.它工作正常,但测试拒绝在代码中返回响应.奇怪的是,它只显示在 CLI 中.

i'm currently testing an app that simply searches a record by the given id. It works fine but the testing refuses to return the response in the code. Strangely it is ONLY shown in the CLI.

我使用的是 cakephp 提供的 phpunit:

I'm using phpunit provided by cakephp:

"phpunit/phpunit": "^5.7|^6.0"

"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 时也会出现同样的问题.但这是目标控制器的代码:

Also the same problem occurrs while doing GET or POST to any other action. But here is the targeted controller's code:

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"方法使用ob_start()"和ob_get_clean()"来获得输出.我希望有一种更清洁的方式......

UPDATE 1: I've only managed to get the output by using "ob_start()" and "ob_get_clean()" around the "$this->post" method. I wish there were a cleaner way though...

更新 2:现在可以使用了!只需使用符合 PSR-7 的接口即可.谢谢!这是更正后的控制器:

UPDATE 2: Now it's working! Just by using the PSR-7 compliant interface. Thank you! Here is the corrected controller:

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
}

推荐答案

控制器操作不应该回显数据,即使它可能在某些甚至大多数情况下工作.输出不是来自渲染视图模板的数据的正确方法是配置并返回响应对象,或者使用序列化视图.

Controller actions are not supposed to echo data, even though it might work in some, maybe even most situations. The correct way of outputting data that doesn't stem from a rendered view template, is to configure and return the response object, or to use serialized views.

测试环境依赖于正确执行此操作,因为它不会缓冲可能的输出,但会使用从控制器操作返回的实际值.

The test environment relies on doing this properly, as it doesn't buffer possible output, but will use the actual value returned from the controller action.

以下基本上是https://stackoverflow.com/a/42379581/1392379的副本

The following is basically a copy from https://stackoverflow.com/a/42379581/1392379

引自文档:

Controller 动作通常使用 Controller::set() 来创建一个上下文,View 用它来渲染视图层.由于 CakePHP 使用的约定,您不需要手动创建和呈现视图.相反,一旦控制器操作完成,CakePHP 将处理渲染和交付视图.

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.

如果出于某种原因您想跳过默认行为,您可以从具有完全创建响应的操作中返回一个 CakeNetworkResponse 对象.

If for some reason you’d like to skip the default behavior, you can return a CakeNetworkResponse object from the action with the fully created response.

* 从 3.4 开始,这将是 CakeHttpResponse

说明书 > 控制器 > 控制器操作

$content = json_encode($comuna);

$this->response->getBody()->write($content);
$this->response = $this->response->withType('json');
// ...

return $this->response;

符合 PSR-7 的接口使用不可变方法,因此使用了 withType() 的返回值.与设置标题和其他内容不同,通过写入现有流来更改正文不会更改响应对象的状态.

The PSR-7 compliant interface uses immutable methods, hence the utilization of the return value of withType(). Unlike setting headers and stuff, altering the body by writing to an existing stream doesn't change the state of the response object.

CakePHP 3.4.3 将添加一个不可变的 withStringBody 方法,该方法可以替代写入现有流.

CakePHP 3.4.3 will add an immutable withStringBody method that can be used alternatively to writing to an existing stream.

$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 发送正确的请求代码> 接受标题.

This requires to also use the request handler component, and to enable extensing parsing and using correponsing URLs with .json appended, or to send a proper request with a application/json accept header.

这篇关于CakePHP 3.4.2 测试 POST 的响应总是返回 NULL的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆