【问题标题】:Laravel Redirect::back()->withErrors() not working in TestLaravel Redirect::back()->withErrors() 在测试中不起作用
【发布时间】:2014-11-14 13:19:33
【问题描述】:

好的,我在为“不正确的凭据”登录(即缺少密码)编写功能测试时遇到了麻烦。

背景是我的路线配置:

Route::get('login', array('as' => 'login', 'uses' => 'SessionController@create'));
Route::resource('session', 'SessionController');

这是我的 SessionController::store() 方法中的内容:

public function store()
{

    $credentials = Input::only('email', 'password');

    try {
        $this->loginForm->validate($credentials);

        if (!Auth::attempt(array('email' => $credentials['email'], 'password' => $credentials['password']))) {
            return Redirect::back()->exceptInput('password')->with('flash_message', 'Invalid credentials');
        }

        return Redirect::to('/')->with('flash_message', 'Welcome back');

    }
    catch (FormValidationException $e)
    {
        return Redirect::back()->exceptInput('password')->withErrors($e->getErrors());
    }

}

当我将带有 POST 操作的表单提交到 /session 时,上述 store() 控制器在浏览器中完美运行(!)。引发表单验证错误,我被重定向回 /login 并在我的视图中使用 $errors 变量正确填充了相关消息(“密码字段是必需的”):

@foreach($errors->all() as $error)
    {{ $error }}
@endforeach

但是,当尝试在功能测试中复制上述预期的工作行为时,我遇到了问题。这是我的测试的基本大纲:

public function testIncorrectCredentialsLogin()
{
    $this->client->request('GET', '/login');

    $this->assertTrue($this->client->getResponse()->isOk());

    $credentials = array(
        'email' => 'me@example.com',
        'password' => ''
    );

    $this->client->request('POST', '/session', $credentials);

    $this->assertRedirectedTo('login', array('errors'));

    $crawler = $this->client->followRedirect();

    $this->assertSessionHasErrors();

    $this->assertHasOldInput();

    $this->assertViewHas('errors'); // Fails

}

在我的功能测试中,我尝试复制浏览器中成功发生的情况。我首先 GET /login,然后在缺少凭据的情况下对 SessionController::store() 进行 /POST,这会导致验证错误并重定向回 /login。到目前为止一切正常,但是当我按照此重定向返回时,我会查看呈现的登录页面内容/HTML,并且我没有设置 $errors 变量,因此会话中没有可用的消息/页面中显示。

谁能告诉我可能会发生什么?

提前致谢。

【问题讨论】:

    标签: php laravel laravel-4 integration-testing functional-testing


    【解决方案1】:

    我不是功能测试方面的专家,但我猜您可能会尝试使用爬虫对象而不是 $this 在 HTML 中查找错误 HTML 代码。当你这样做时:

    $crawler = $this->client->followRedirect();

    对我来说意味着现在爬虫已经通过重定向生成了 HTML。

    希望对你有帮助

    【讨论】:

    • 谢谢elfif。我已经尝试了以下建议(错误消息显示在警报框 div 中): $this->assertCount(1, $crawler->filter("div.alert-box"));这将返回 false(警告框不在内容中)。如果我只是 $this->client->getResponse()->getContent() 也不会显示错误消息。好像是在我查看之前删除了错误 Flash 会话?
    • 无法使用爬虫删除内容,因为 javascript 不被爬虫 AFAIK 解释。要么内容从一开始就存在,要么不存在。
    【解决方案2】:

    在控制器中:

    return back()->withErrors('name' => 'name is required!');

    在刀片中(视图):

    <input
            type="text"
            id="name"
            class="form-control dt-uname @error('name') is-invalid @enderror"
            placeholder=""
            aria-label="jdoe1"
            aria-describedby="basic-icon-default-uname2"
            name="name"
            value="{{ old('name') }}"
    
    />
    @error('name')
        <span class="invalid-feedback" role="alert">
            <strong>{{ $message }}</strong>
        </span>
    @enderror
    

    【讨论】:

      【解决方案3】:

      withErrors 必须是一个数组

      在单元测试中对我有用,因为它是一个数组 []

      return redirect()->route('projects')->withErrors(['Something went wrong']);
      

      但这行不通

      return redirect()->route('projects')->withErrors('error', 'Something went wrong');
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-06-30
        • 2023-03-07
        • 2015-06-04
        相关资源
        最近更新 更多