如何使用 PhpUnit 使用 Laravel 测试服务?

Ite*_*tor 8 php phpunit laravel

我想测试我的一些服务,但在 Laravel 的网站上找不到任何示例:https ://laravel.com/docs/5.1/testing

他们展示了如何测试简单的类、实体、控制器,但我不知道如何测试服务。如何实例化具有复杂依赖关系的服务?


示例服务:

<?php

namespace App\Services;

// Dependencies
use App\Services\FooService;
use App\Services\BarService;

class DemoService {

    private $foo_srv;
    private $bar_srv;

    function __construct(
        FooService $foo_srv,
        BarService $bar_srv
    ) {
        $this->foo_srv = $foo_srv;
        $this->bar_srv = $bar_srv;
    }

    // I would like to test these two functions

    public function demoFunctionOne() {
        // ...
    }

    public function demoFunctionTwo() {
        // ...
    }

}
Run Code Online (Sandbox Code Playgroud)

Olu*_*kin 6

可能想到的最快的想法是创建这些 Service 类的副本,但这可能会变得如此之大。这就是 PhpUnit 中有 MockObject 的原因。

要实现此模拟并将其用作服务类的替代品,您可能需要在 Laravel 服务容器中解析它。

这是它的外观:

class DemoServiceTest extends TestCase
{
    // Dependencies
    use App\Services\FooService;
    use App\Services\BarService;
    use App\Services\DemoService;

    public function testDemoFunctionOne()
    {
        $foo_srv = $this->getMockBuilder(FooService::class)
            //->setMethods(['...']) // array of methods to set initially or they return null
            ->disableOriginalConstructor() //disable __construct
            ->getMock();
         /**
          * Set methods and value to return
          **/
        // $foo_srv->expects($this->any())
        //    ->method('myMethod') //method needed by DemoService?
        //    ->will($this->returnValue('some value')); // return value expected

        $bar_srv = $this->getMockBuilder(BarService::class)
//            ->setMethods(['...']) // array of methods to set initially or they return null
            ->disableOriginalConstructor()
            ->getMock();

        /**
         * Set methods and value to return
         **/
        // $bar_srv->expects($this->any())
        //    ->method('myMethod') //method needed by DemoService?
        //    ->will($this->returnValue('some value')); // return value expected

        $demo_service = new DemoService($foo_srv, $bar_srv);
        $result = $demo_service->demoFunctionOne(); //run demo function

        $this->assertNotEmpty($result); //an assertion
    }
}
Run Code Online (Sandbox Code Playgroud)

我们正在为FooServiceBarService类创建新的模拟,然后在实例化DemoService.

如您所见,在不取消注释的代码块的情况下,我们设置了一个返回值,否则当setMethods不使用时,所有方法默认返回 null。

假设您想在 Laravel 服务容器中解析这些类,然后您可以在创建模拟后调用:

$this->app->instance(FooService::class, $foo_srv);
$this->app->instance(BarService::class, $bar_srv);
Run Code Online (Sandbox Code Playgroud)

Laravel 解析这两个类,将模拟类提供给类的任何调用者,这样你就可以这样调用你的类:

$demoService = $this->app->make(DemoService::class);
Run Code Online (Sandbox Code Playgroud)

在模拟测试类时需要注意很多事情,请参阅来源:https : //matthiasnoback.nl/2014/07/test-doubles/,https : //phpunit.de/manual/6.5/en/test -doubles.html