在 Laravel 5 中,为什么在 phpunit 测试期间调用 Request::root() 不同?

In Laravel 5, why is Request::root() different when called during phpunit test?

我定义了一个测试用户创建的测试。控制器设置为在出错时重定向回同一页面(通过生成的 App\Http\Requests\Request 使用验证)。这在浏览器中手动单击时可以正常工作,但在测试期间会失败。而不是被重定向到:

http://localhost/account/create

测试重定向到(缺少斜线):

http://localhostaccount/create

这些网址都不是我在 .htaccess 或 config/app.php 中的 $url 变量中设置的。这是(在 OSX Yosemite):

http://~username/laravel_projects/projectname/public

我最终确定问题与 Request::root() 的结果生成方式有关。在测试之外调用它会产生 .htaccess 和 $url 中定义的预期值。在测试中它导致:

http://localhost

需要更改什么配置才能使此函数在两种情况下都成为 return 正确的值?

我还应该提到我从 Laravel 4 痛苦地升级到当前版本 5.0.27。

****** 更新 *******

我想出了一个可以接受的 solution/workaround 这个问题!

在 Laravel 5 中,引入了 FormRequests 以帮助将 validation 逻辑移出控制器。将请求映射到控制器后,如果指定了 FormRequest(或仅 Request),则会在点击控制器操作之前执行。

如果验证失败,默认情况下 FormRequest 会处理响应。它会尝试根据您将表单数据发布到的路由构建重定向。在我的例子中,可能与我从 Laravel 4 更新到 5 的错误有关,这个默认重定向的构造不正确。 Laravel System 处理响应的代码如下所示:

 /**
 * Get the proper failed validation response for the request.
 *
 * @param  array  $errors
 * @return \Symfony\Component\HttpFoundation\Response
 */
public function response(array $errors)
{
    if ($this->ajax() || $this->wantsJson())
    {
        return new JsonResponse($errors, 422);
    }
    return $this->redirector->to($this->getRedirectUrl())
                                    ->withInput($this->except($this->dontFlash))
                                    ->withErrors($errors, $this->errorBag);
}

请注意 returned 重定向与调用 Redirect::route('some_route') 不同。您可以通过在 Request class.

中包含 use Responseoverride 这个 response 函数

在使用 Redirect::route() 创建重定向后,我的测试逻辑通过了预期结果。这是我有效的请求代码:

namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;
use App\Http\Requests\Request;
use Response;

class AccountRequest extends FormRequest {

    /**
     * Determine if the user is authorized to make this request.
     *
     * @return bool
     */
    public function authorize()
    {
        return true;
    }

    /**
     * Get the validation rules that apply to the request.
     *
     * @return array
     */
    public function rules()
    {
        return [
                  'email' => 'required|max:50|email|unique:users',
                  'password' => 'required|min:6',
                  'password_confirmation' => 'required|same:password'

                ];
    }

  public function response(array $errors){
    return \Redirect::route('account_create');
  }

}

重要的部分是我调用了 Redirect::route 而不是让默认响应代码执行。

您需要更改 config/app.php 文件的 url 值。默认值为 http://localhost

文档来自 config/app.php

控制台使用此 URL 在使用 Artisan 命令行工具时正确生成 URLs。您应该将其设置为应用程序的根目录,以便在 运行 Artisan 任务时使用它。

我知道这不是您问题的准确答案,因为它不是解决问题的配置更新。但是我一直在努力解决一个相关的问题,这似乎是互联网上唯一一个处理类似问题的人 post - 我想我会为任何想要不同修复的人投入我的两分钱。

请注意,我目前使用的是 Laravel 4.2,因此这可能在 Laravel 5 中发生了变化(尽管我对此表示怀疑)。

您可以在使用函数测试控制器时指定 HTTP_HOST header:

$response = $this->call($method, $uri, $parameters, $files, $server, $content);

要指定 header,只需提供 $server 变量作为数组,如下所示:

array('HTTP_HOST' => 'testing.mydomain.com');

当我执行上述操作时,为我的 Request::root() 产生的价值是 http://testing.mydomain.com

同样,我知道这不是解决您问题的配置更新,但希望这可以帮助那些正在努力解决 semi-related 问题的人。

Override the response function 在 FormRequest 验证处理程序中强制使用 Redirect::route('named_route') 构造重定向,而不是允许默认重定向。

如果您尝试更改 config/app.php 但没有帮助。

最好使用 $_ENV - phpunit 中的全局变量。

说,你想要 Request::root() 到 return 'my.site'

但是你不能触摸phpunit.xml

你可以像这样简单地设置一个环境参数

$_ENV['APP_URL'] = 'my.site';

并在单元测试中调用 $this->refreshApplication();

中提琴,你的 request()->root() 现在给你 my.site