【问题标题】:Laravel 4.2 : testing with assertRedirectedToRoute failsLaravel 4.2:使用 assertRedirectedToRoute 测试失败
【发布时间】:2015-03-16 13:03:57
【问题描述】:

我想知道是否有其他人遇到过这个问题。我正在阅读 Jeffrey Way 的关于 Laravel 测试的书,我正在阅读解释如何测试控制器的章节。

当我按照书中的例子进行操作时 - 我得到了信息:

无法断言 Illuminate\Http\Response 对象 (...) 是 “Illuminate\Http\RedirectResponse”类的实例。

我的测试如下:

public function testStoreFails()
    {

        $input = ['title' => ''];

        $this->mock
                ->shouldReceive('create')
                ->once()
                ->with($input);

        $this->app->instance('Post', $this->mock);

        $this->post('posts', $input);

        $this->assertRedirectedToRoute('posts.create');

        $this->assertSessionHasErrors(['title']);

    }

以及控制器中非常简单的方法(只是为了测试这个特定的场景):

public function create()
    {

        $input = Input::all();

        $validator = Validator::make($input, ['title' => 'required']);

        if ($validator->fails()) {

            return Redirect::route('posts.create')
                    ->withInput()
                    ->withErrors($validator->messages());

        }

        $this->post->create($input);

        return Redirect::route('posts.index')
                ->with('flash', 'Your post has been created!');

    }

据我所知,AssertionsTrait::assertRedirectedTo 检查 Illuminate\Http\RedirectResponse 的实例

/**
     * Assert whether the client was redirected to a given URI.
     *
     * @param  string  $uri
     * @param  array   $with
     * @return void
     */
    public function assertRedirectedTo($uri, $with = array())
    {
        $response = $this->client->getResponse();

        $this->assertInstanceOf('Illuminate\Http\RedirectResponse', $response);

        $this->assertEquals($this->app['url']->to($uri), $response->headers->get('Location'));

        $this->assertSessionHasAll($with);
    }

    /**
     * Assert whether the client was redirected to a given route.
     *
     * @param  string  $name
     * @param  array   $parameters
     * @param  array   $with
     * @return void
     */
    public function assertRedirectedToRoute($name, $parameters = array(), $with = array())
    {
        $this->assertRedirectedTo($this->app['url']->route($name, $parameters), $with);
    }

这应该可以正常工作,因为 Redirect 外观解析为 Illuminate\Routing\Redirector 及其 route() 方法调用 createRedirect(),它返回 Illuminate\Http\RedirectResponse 的实例 - 所以不太确定是什么原因造成的。

更新:

刚刚再次检查了代码,看起来问题出在AssertionsTrait::assertRedirectedTo() 方法中。对$this->client->getResponse() 的调用返回Illuminate\Http\Response 的实例而不是Illuminate\Http\RedirectResponse - 因此$this->assertInstanceOf('Illuminate\Http\RedirectResponse', $response) 调用失败。但我仍然不确定为什么 - 我正在扩展 TestCase,它应该负责所有环境设置等。有什么想法吗?

【问题讨论】:

  • 假设您正在使用资源,那么您在 create 方法中的逻辑实际上应该放在 store 方法中。 post/create 应该只返回带有表单的视图以输入数据,然后 store 方法获取输入数据并实际创建和存储对象。所以:$this->post('posts', $input); 不会调用你的create() 方法,而是调用你的store() 方法。所以看看它,如果它不存在,你可能只是得到一个 404 响应,这不是重定向。
  • 你是对的@Quasdunk - 感谢您指出这一点。您可以将其发布为答案以便我接受吗?

标签: php laravel laravel-4 laravel-testing


【解决方案1】:

发表评论作为答案:

由于你正在使用一个资源丰富的对象,Laravel 会自动为你创建一些路由,即:

+-----------------------------+---------------+-------------------------+
| URI                         | Name          | Action                  |
+-----------------------------+---------------+-------------------------+
| GET|HEAD posts              | posts.index   | PostsController@index   |
| GET|HEAD posts/create       | posts.create  | PostsController@create  |
| POST posts                  | posts.store   | PostsController@store   |
| GET|HEAD posts/{posts}      | posts.show    | PostsController@show    |
| GET|HEAD posts/{posts}/edit | posts.edit    | PostsController@edit    |
| PUT posts/{posts}           | posts.update  | PostsController@update  |
| PATCH posts/{posts}         |               | PostsController@update  |
| DELETE posts/{posts}        | posts.destroy | PostsController@destroy |
+-----------------------------+---------------+-------------------------+

如您所见,对 /posts 的 POST 请求(正如您在测试中所做的那样)会触发 PostsController 上的 store() 方法,而不是您假设正在测试的 create() 方法。

createstore 以及 editupdate 有时会让人感到困惑。区别如下:

  • create() - 显示创建新资源的表单
  • store() - 实际从发布的数据创建资源

  • edit($id) - 显示编辑指定资源的表单
  • update($id) - 实际使用发布的数据更新资源

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-02-27
    • 1970-01-01
    • 2015-04-15
    • 2021-07-12
    • 2022-07-25
    • 2015-02-05
    • 2017-05-24
    相关资源
    最近更新 更多