Laravel和Codeception - 测试在PUT表单上失败 [英] Laravel and Codeception - test fails on PUT forms

查看:167
本文介绍了Laravel和Codeception - 测试在PUT表单上失败的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在laravel有一个资源控制器来管理我的用户。这创建了一条更新用户信息的路线,它使用HTTP PUT方法接受请求。



这显示了 artisan route:list 命令输出:

  + -------- + ------------ -------------------- + ----------------------------- ------------------------------ + ------------------- ------------------- + ------------------------------ -------------------------------------------------- + ------------ + 
|域|方法| URI |名称|操作|中间件|
+ -------- + -------------------------------- + --- -------------------------------------------------- ------ + -------------------------------------- + ---- -------------------------------------------------- -------------------------- + ------------ +
...
| | PUT |用户/ {users} | users.update | App \Http\Controllers\Users\UsersController @ update | auth |

它可以在我的网页浏览器上正常运行,但是当我尝试使用代码运行测试时,形式我得到一个方法不允许异常和测试失败。



我想知道为什么会发生这种情况,它似乎是由codeception提出的请求。该请求使用POST而不是PUT方法来阻止Laravel匹配路由。



HTML表单不支持PUT方法,所以Laravel Form helper类创建如下表单:

 < form method =POSTaction =https ://myapp.dev/users/172accept-charset =UTF-8> 
< input name =_ methodvalue =PUTtype =hidden>
...

然而,它似乎并没有读取 _method value。



我该如何解决这个问题?深入研究代码,我发现测试不会覆盖请求方法,因为 Request 类中有一个常量 Request :: $ httpMethodParameterOverride

  / ** 
*获取请求预期方法。
*
*如果设置了X-HTTP-Method-Override标头,并且该方法是POST,则
*用于确定实际预期的HTTP方法。
*
*只有在调用了enableHttpMethodParameterOverride()时,_method请求参数才可用于确定HTTP方法
*。
*
*该方法始终是大写字符串。
*
* @return string请求方法
*
* @api
*
* @get getRealMethod()
* /
public function getMethod()
{
if(null === $ this-> method){
$ this-> method = strtoupper($ this-> server - > get('REQUEST_METHOD','GET'));

if('POST'=== $ this-> method){
if($ method = $ this-> headers-> get('X-HTTP-METHOD -OVERRIDE')){
$ this-> method = strtoupper($ method);
} elseif(self :: $ httpMethodParameterOverride){
$ this-> method = strtoupper($ this-> request-> get('_ method',$ this-> query-> ; get('_ method','POST')));
}
}
}

返回$ this->方法;
}

以前的常量值应该是 true ,但是当我运行测试时,它的值是 false

解决方案 div>

我找到了一个解决方案,但我认为这不是写它的正确地方。
我在 Connector \Laravel5 类中添加了一行简单的代码。

  public function __construct($ module)
{
$ this-> module = $ module;
$ this-> initialize();

$ components = parse_url($ this-> app ['config'] - > get('app.url','http:// localhost'));
$ host = isset($ components ['host'])? $ components ['host']:'localhost';

parent :: __ construct($ this-> app,['HTTP_HOST'=> $ host]);

//父构造函数默认为不重定向
$ this-> followRedirects(true);

//新增来解决重写请求方法的问题
Request :: enableHttpMethodParameterOverride();
}

这解决了我的问题。


I have a resource controller in laravel to manage my users. This creates a route to update users info that takes a request with HTTP PUT method.

This shows artisan route:list command output:

+--------+--------------------------------+-----------------------------------------------------------+--------------------------------------+--------------------------------------------------------------------------------+------------+
| Domain | Method                         | URI                                                       | Name                                 | Action                                                                         | Middleware |
+--------+--------------------------------+-----------------------------------------------------------+--------------------------------------+--------------------------------------------------------------------------------+------------+
...
|        | PUT                            | users/{users}                                             | users.update                         | App\Http\Controllers\Users\UsersController@update                              | auth       |

It works correctly on my web browser but when I try to run a test with codeception and I submit the form I get a method not allowed exception and the test fails.

I tried to see why this is happening and it seems to be the request made by codeception. That request is made with POST instead of PUT method preventing Laravel from matching the route.

HTML forms doesn't suport PUT methods so Laravel Form helper class creates the form as follows:

<form method="POST" action="https://myapp.dev/users/172" accept-charset="UTF-8">
    <input name="_method" value="PUT" type="hidden">
...

However, it seems that codeception is not reading the _method value.

How can I fix this?

EDIT: Looking deeply on the code I found that test don't override the request method beacause of a constant in th Request class called Request::$httpMethodParameterOverride.

/**
 * Gets the request "intended" method.
 *
 * If the X-HTTP-Method-Override header is set, and if the method is a POST,
 * then it is used to determine the "real" intended HTTP method.
 *
 * The _method request parameter can also be used to determine the HTTP method,
 * but only if enableHttpMethodParameterOverride() has been called.
 *
 * The method is always an uppercased string.
 *
 * @return string The request method
 *
 * @api
 *
 * @see getRealMethod()
 */
public function getMethod()
{
    if (null === $this->method) {
        $this->method = strtoupper($this->server->get('REQUEST_METHOD', 'GET'));

        if ('POST' === $this->method) {
            if ($method = $this->headers->get('X-HTTP-METHOD-OVERRIDE')) {
                $this->method = strtoupper($method);
            } elseif (self::$httpMethodParameterOverride) {
                $this->method = strtoupper($this->request->get('_method', $this->query->get('_method', 'POST')));
            }
        }
    }

    return $this->method;
}

The previous constant value should be true but shomehow, when I run the test its value is false.

解决方案

I found a solution but I don't think this is the right place to write it. I added a simple line of code on the Connector\Laravel5 class.

public function __construct($module)
{
    $this->module = $module;
    $this->initialize();

    $components = parse_url($this->app['config']->get('app.url', 'http://localhost'));
    $host = isset($components['host']) ? $components['host'] : 'localhost';

    parent::__construct($this->app, ['HTTP_HOST' => $host]);

    // Parent constructor defaults to not following redirects
    $this->followRedirects(true);

    // Added to solve the problem of overriding the request method
    Request::enableHttpMethodParameterOverride();
}

This solves my problem.

这篇关于Laravel和Codeception - 测试在PUT表单上失败的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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