Laravel 4.2:使用 assertRedirectedToRoute 进行测试失败
Laravel 4.2 : testing with assertRedirectedToRoute fails
我想知道是否还有其他人遇到过这个问题。我正在阅读 Jeffrey Way 在 Laravel 中关于测试的书,我正在阅读解释如何测试控制器的章节。
当我按照书中的示例进行操作时 - 我收到消息:
Failed asserting that Illuminate\Http\Response Object (...) is an
instance of class "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 facade 解析为 Illuminate\Routing\Redirector
并且它的 route()
方法调用 createRedirect()
时,它应该工作得很好,returns [=15] 的实例=] - 所以不太确定是什么原因造成的。
更新:
刚刚再次检查了代码,看起来问题出在 AssertionsTrait::assertRedirectedTo()
方法中。调用 $this->client->getResponse()
returns 实例 Illuminate\Http\Response
而不是 Illuminate\Http\RedirectResponse
- 因此 $this->assertInstanceOf('Illuminate\Http\RedirectResponse', $response)
调用失败。但我仍然不确定为什么 - 我正在扩展 TestCase
,它应该负责所有环境设置等。有什么想法吗?
发表评论作为回答:
由于您正在使用一个足智多谋的对象,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()
方法您假设正在接受测试。
create
和 store
以及 edit
和 update
有时会令人困惑。区别如下:
create()
- 显示创建新资源的表单
store()
- 根据发布的数据实际创建资源
edit($id)
- 显示编辑指定资源的表单
update($id)
- 使用发布的数据实际更新资源
我想知道是否还有其他人遇到过这个问题。我正在阅读 Jeffrey Way 在 Laravel 中关于测试的书,我正在阅读解释如何测试控制器的章节。
当我按照书中的示例进行操作时 - 我收到消息:
Failed asserting that Illuminate\Http\Response Object (...) is an instance of class "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 facade 解析为 Illuminate\Routing\Redirector
并且它的 route()
方法调用 createRedirect()
时,它应该工作得很好,returns [=15] 的实例=] - 所以不太确定是什么原因造成的。
更新:
刚刚再次检查了代码,看起来问题出在 AssertionsTrait::assertRedirectedTo()
方法中。调用 $this->client->getResponse()
returns 实例 Illuminate\Http\Response
而不是 Illuminate\Http\RedirectResponse
- 因此 $this->assertInstanceOf('Illuminate\Http\RedirectResponse', $response)
调用失败。但我仍然不确定为什么 - 我正在扩展 TestCase
,它应该负责所有环境设置等。有什么想法吗?
发表评论作为回答:
由于您正在使用一个足智多谋的对象,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()
方法您假设正在接受测试。
create
和 store
以及 edit
和 update
有时会令人困惑。区别如下:
create()
- 显示创建新资源的表单store()
- 根据发布的数据实际创建资源
edit($id)
- 显示编辑指定资源的表单update($id)
- 使用发布的数据实际更新资源