如何在 Laravel 5 中测试路由,或者尝试 "MockStub" 某些东西,或者我不知道 TDD
How to test routes in Laravel 5, or Trying to "MockStub" something, or I have no idea of TDD
我从 TDD 和 Laravel 开始。具体来说,我从路线开始。我定义了一些,但我定义得很糟糕,因为我对 TDD 的 "new" 概念感到非常兴奋,所以我想为它们编写一些测试。
我的想法是单独测试路由,并且只测试路由,正如我阅读的有关 TDD 的所有内容所推荐的那样。我知道我可以做 $this->call->('METHOD','something')
并且测试响应正常或其他,但我想知道调用了正确控制器的正确方法。
所以,我想我可以模拟控制器。这是我的第一次尝试:
public function test_this_route_work_as_expected_mocking_the_controller()
{
//Create the mock
$drawController = \Mockery::mock('App\Http\Controllers\DrawController');
$drawController->shouldReceive('show')->once();
// Bind instance of my controller to the mock
App::instance('App\Http\Controllers\DrawController', $drawController);
$response = $this->call('GET','/draw/1');
// To see what fails. .env debugging is on
print($response);
}
路线是Route::resource('draw', 'DrawController');
,我知道没问题。但是不会调用方法 show。在响应中可以看到:"Method Mockery_0_App_Http_Controllers_DrawController::getAfterFilters() does not exist on this mock object"。所以我尝试:
$drawController->getAfterFilters()->willReturn(array());
但我得到:
BadMethodCallException: Method Mockery_0_App_Http_Controllers_DrawController::getAfterFilters() does not exist on this mock object
经过一些测试,我得出了这个解决方案:
public function test_this_route_work_as_expected_mocking_the_controller_workaround()
{
//Create the mock
$drawController = \Mockery::mock('App\Http\Controllers\DrawController');
// These are the methods I would like to 'stub' in this mock
$drawController->shouldReceive('getAfterFilters')->atMost(1000)->andReturn(array());
$drawController->shouldReceive('getBeforeFilters')->atMost(1000)->andReturn(array());
$drawController->shouldReceive('getMiddleware')->atMost(1000)->andReturn(array());
// This is where the corresponding method is called. I can assume all is OK if we arrive here with
// the right method name:
// public function callAction($method, $parameters)
$drawController->shouldReceive('callAction')->once()->with('show',Mockery::any());
// Bind instance of my controller to the mock
App::instance('App\Http\Controllers\DrawController', $drawController);
//Act
$response = $this->call('GET','/draw/1');
}
但我想将 shouldReceives
更改为 willReturns
:atMost(1000)
伤了我的眼睛。所以我的问题是:
1) 是否有更简洁的方法来仅测试 Laravel 5 中的路由?我的意思是,理想的场景是控制器不存在,但如果路线没问题,测试通过
2) 是否可以 "MockStub" 控制器?更好的方法是什么?
非常感谢。
我终于明白了。您需要一个 部分模拟 。它可以像这样简单地完成(诀窍是包括一个 "array" 方法来模拟 Mockery::mock):
public function test_this_route_work_as_expected_mocking_partially_the_controller()
{
//Create the mock
$drawController = \Mockery::mock('App\Http\Controllers\DrawController[show]');
$drawController->shouldReceive('show')->once();
// Bind instance of my controller to the mock
App::instance('App\Http\Controllers\DrawController', $drawController);
//Act
$this->call('GET','/draw/1');
}
并且,如果您在 setup()
方法中创建所有控制器的部分模拟,所有路由测试都可以分组到一个(或几个)TestCases
我从 TDD 和 Laravel 开始。具体来说,我从路线开始。我定义了一些,但我定义得很糟糕,因为我对 TDD 的 "new" 概念感到非常兴奋,所以我想为它们编写一些测试。
我的想法是单独测试路由,并且只测试路由,正如我阅读的有关 TDD 的所有内容所推荐的那样。我知道我可以做 $this->call->('METHOD','something')
并且测试响应正常或其他,但我想知道调用了正确控制器的正确方法。
所以,我想我可以模拟控制器。这是我的第一次尝试:
public function test_this_route_work_as_expected_mocking_the_controller()
{
//Create the mock
$drawController = \Mockery::mock('App\Http\Controllers\DrawController');
$drawController->shouldReceive('show')->once();
// Bind instance of my controller to the mock
App::instance('App\Http\Controllers\DrawController', $drawController);
$response = $this->call('GET','/draw/1');
// To see what fails. .env debugging is on
print($response);
}
路线是Route::resource('draw', 'DrawController');
,我知道没问题。但是不会调用方法 show。在响应中可以看到:"Method Mockery_0_App_Http_Controllers_DrawController::getAfterFilters() does not exist on this mock object"。所以我尝试:
$drawController->getAfterFilters()->willReturn(array());
但我得到:
BadMethodCallException: Method Mockery_0_App_Http_Controllers_DrawController::getAfterFilters() does not exist on this mock object
经过一些测试,我得出了这个解决方案:
public function test_this_route_work_as_expected_mocking_the_controller_workaround()
{
//Create the mock
$drawController = \Mockery::mock('App\Http\Controllers\DrawController');
// These are the methods I would like to 'stub' in this mock
$drawController->shouldReceive('getAfterFilters')->atMost(1000)->andReturn(array());
$drawController->shouldReceive('getBeforeFilters')->atMost(1000)->andReturn(array());
$drawController->shouldReceive('getMiddleware')->atMost(1000)->andReturn(array());
// This is where the corresponding method is called. I can assume all is OK if we arrive here with
// the right method name:
// public function callAction($method, $parameters)
$drawController->shouldReceive('callAction')->once()->with('show',Mockery::any());
// Bind instance of my controller to the mock
App::instance('App\Http\Controllers\DrawController', $drawController);
//Act
$response = $this->call('GET','/draw/1');
}
但我想将 shouldReceives
更改为 willReturns
:atMost(1000)
伤了我的眼睛。所以我的问题是:
1) 是否有更简洁的方法来仅测试 Laravel 5 中的路由?我的意思是,理想的场景是控制器不存在,但如果路线没问题,测试通过
2) 是否可以 "MockStub" 控制器?更好的方法是什么?
非常感谢。
我终于明白了。您需要一个 部分模拟 。它可以像这样简单地完成(诀窍是包括一个 "array" 方法来模拟 Mockery::mock):
public function test_this_route_work_as_expected_mocking_partially_the_controller()
{
//Create the mock
$drawController = \Mockery::mock('App\Http\Controllers\DrawController[show]');
$drawController->shouldReceive('show')->once();
// Bind instance of my controller to the mock
App::instance('App\Http\Controllers\DrawController', $drawController);
//Act
$this->call('GET','/draw/1');
}
并且,如果您在 setup()
方法中创建所有控制器的部分模拟,所有路由测试都可以分组到一个(或几个)TestCases