如何在 Laravel 5 中测试路线,或者尝试“MockStub”,或者我不知道 TDD
Posted
技术标签:
【中文标题】如何在 Laravel 5 中测试路线,或者尝试“MockStub”,或者我不知道 TDD【英文标题】:How to test routes in Laravel 5, or Trying to "MockStub" something, or I have no idea of TDD 【发布时间】:2015-06-07 23:13:00 【问题描述】:我从 TDD 和 Laravel 开始。具体来说,我从路线开始。我定义了一些,但我定义得很糟糕,当我对 TDD 的“新”概念感到兴奋时,我想为它们编写一些测试。
我们的想法是单独测试路由,并且只测试路由,因为我读过的所有关于 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() 在这个模拟对象上不存在”。所以我尝试:
$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”控制器?有什么更好的方法?
非常感谢。
【问题讨论】:
【参考方案1】:我终于明白了。您需要一个部分模拟。它可以像这样简单地完成(诀窍是包含一个“数组”方法来模拟 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 中
【讨论】:
顺便说一句,更多信息在这里:docs.mockery.io/en/latest/reference/partial_mocks.html 感谢您提出这个问题!以上是关于如何在 Laravel 5 中测试路线,或者尝试“MockStub”,或者我不知道 TDD的主要内容,如果未能解决你的问题,请参考以下文章