如何测试 Laravel 5 控制器方法

Posted

技术标签:

【中文标题】如何测试 Laravel 5 控制器方法【英文标题】:How to test Laravel 5 controllers methods 【发布时间】:2015-06-29 03:20:33 【问题描述】:

我们有 Laravel 5 控制器方法:

public function getInput()

    $input = \Request::all();
    $links = $input['links'];
    $this->startLinks =  explode("\n", $links);
    return $this;

我们如何测试这个单一的方法?如何将带有数据的 POST 请求传递给此方法?以及如何在我的测试方法中创建这个控制器类的实例?

【问题讨论】:

【参考方案1】:

这看起来像是一个可能不应该属于控制器的方法。如果您认真对待测试,我强烈建议您阅读存储库模式。在测试时,将所有东西都从控制器中抽象出来会让你的生活变得更轻松。=

话虽如此,这仍然是非常可测试的。主要思想是找出需要测试的内容并仅对其进行测试。这意味着我们不关心依赖项在做什么,只关心它们正在做什么并返回方法的其余部分需要的东西。在本例中,它是 Request 外观。

然后,您要确保变量设置正确并且该方法返回了该类的实例。它实际上最终非常简单。

应该看起来像这样......

public function testGetInput()

    $requestParams = [
        'links' => "somelink.com\nsomeotherlink.com\nandanotherlink.com\ndoesntmatter.com"
    ];

    // Here we are saying the \Request facade should expect the all method to be called and that all method should
    // return some pre-defined things which we will use in our asserts.
    \Request::shouldReceive('all')->once()->andReturn($requestParams);

    // Here we are just using Laravel's IoC container to instantiate your controller.  Change YourController to whatever
    // your controller is named
    $class = App::make('YourController');

    // Getting results of function so we can test that it has some properties which were supposed to have been set.
    $return = $class->getInput();

    // Again change this to the actual name of your controller.
    $this->assertInstanceOf('YourController', $return);

    // Now test all the things.
    $this->assertTrue(isset($return->startLinks));
    $this->assertTrue(is_array($return->startLinks));
    $this->assertTrue(in_array('somelink.com', $return->startLInks));
    $this->assertTrue(in_array('nsomeotherlink.com', $return->startLInks));
    $this->assertTrue(in_array('nandanotherlink.com', $return->startLInks));
    $this->assertTrue(in_array('ndoesntmatter.com', $return->startLInks));

【讨论】:

非常感谢,您的回答是——这正是我所需要的!但是当我把这条线放到我的测试中时:\Request::shouldReceive('all')->once()->andReturn($requestParams); 当我运行 phpunit 时,我收到了这个异常:PHP Fatal error: Class 'Mockery' not found in /var/www/site.loc/www/vendor/laravel/framework/src/Illuminate/Support/Facades/Facade.php on line 86 [Symfony\Component\Debug\Exception\FatalErrorException] Class 'Mockery' not found 请问您能帮忙吗? 哦,对不起,我忘记了使用嘲讽。查看github.com/padraic/mockery/tree/master 了解安装说明。应该只是composer.json中的一个新的必需项目【参考方案2】:

我想你正在寻找this。

如果您的测试类扩展 TestCase,您将获得许多帮助方法,这些方法将为您完成繁重的工作。

function testSomething() 
    // POST request to your controller@action
    $response = $this->action('POST', 'YourController@yourAction', ['links' => 'link1 \n link2']);
    // you can check if response was ok
    $this->assertTrue($response->isOk(), "Custom message if something went wrong");
    // or if view received variable
    $this->assertViewHas('links', ['link1', 'link2']);

Codeception 进一步扩展了此功能。

【讨论】:

以上是关于如何测试 Laravel 5 控制器方法的主要内容,如果未能解决你的问题,请参考以下文章

Laravel 5 - 如何从 Artisan 命令运行控制器方法?

如何在 Laravel 5.6 中向资源控制器添加自定义方法

如何通过 post 方法将数据从 ajax 传递到 laravel 5.2 控制器

Laravel 5如何通过控制器的登录方法从url获取参数

如何通过邮件方法将数据从 ajax 传输到 laravel 5.2 控制器

Laravel 5.5 中 PHP 单元测试中的类验证器错误