如何在 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 更改为 willReturnsatMost(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