如何在 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 更改为willReturnsatMost(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的主要内容,如果未能解决你的问题,请参考以下文章

Laravel 5:如何获取所有路线的路径?

Laravel 5.1-5.8 中以前的路线名称

在 laravel 4 中使用 phpunit 测试 POST

Laravel 5.4 Api 路线 401

如何在 Laravel 5.8 中附加授权标头

Laravel 5:404 路线上的会话