Laravel和Codeception - 在PUT表单上测试失败

时间:2016-01-21 11:28:29

标签: php forms laravel laravel-5 codeception

我在laravel中有一个资源控制器来管理我的用户。这将创建一条路径来更新使用HTTP PUT方法接收请求的用户信息。

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

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

它在我的网络浏览器上正常工作但是当我尝试使用代码运行测试并且我提交表单时,我得到一个方法不允许异常并且测试失败。

我试图了解为什么会发生这种情况,这似乎是代码生成的请求。该请求是使用POST而不是PUT方法来阻止Laravel匹配路由。

HTML表单不支持PUT方法,因此Laravel Form帮助程序类创建表单如下:

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

但是,似乎代码不会读取_method值。

我该如何解决这个问题?

编辑:深入研究代码我发现测试不会覆盖请求方法,因为RequestRequest::$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;
}

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

2 个答案:

答案 0 :(得分:2)

我找到了一个解决方案,但我不认为这是写它的正确位置。 我在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]);

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

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

这解决了我的问题。

答案 1 :(得分:0)

您无法在HTML表单标记中使用PUT方法。为此,您需要使用laravel的刀片模板格式来定义表单标记。

e.g。 {!! Form::open(['url' => 'users/{users}','method' => 'put','id' => 'form' ]) !!}

此外,您可以使用route属性来定义路线,而不是url