【问题标题】:How to mock or stub with Laravel, PHPUnit, Prophecy, DI如何使用 Laravel、PHPUnit、Prophecy、DI 模拟或存根
【发布时间】:2016-05-28 00:41:54
【问题描述】:

您好,我正在尝试使用 Prophecy 进行我的第一个模拟或存根测试。我从未使用过模拟和存根或嘲弄。我已经完成了相当多的单元测试,其中依赖项并没有真正发挥作用,等等。

如果我可以让这个测试正常工作,我认为它将帮助我进一步测试我的代码。任何帮助将不胜感激!

首先是错误...

Method `Double\App\Services\Maintenance\Flags\MaintenanceFlagsProvider\P1::findMostRecentByLabel()` is not defined.
/Library/WebServer/App/tests/unit/MaintenanceStatusTests.php:21

这里是测试类的相关部分...

use App\Services\Maintenance\Logs\MaintenanceLogProvider;
use App\Services\Maintenance\Flags\MaintenanceFlagsProvider;
use App\Services\Maintenance\NextDueSchedules\NextDueScheduleProvider;
use App\Services\Components\Requirements\Status\RequirementStatusProvider;
use App\Services\Components\Requirements\Properties\ComponentRequirementPropertiesProvider;

class MaintenanceStatusTests extends TestCase
{
    /** @test */
    public function is_initial_returns_true()
    {
        $status = $this->buildStatus();

        $status->maintenance_flags_provider->shouldReceive('findMostRecentByLabel')->andReturn(new MaintenanceFlag(['value' => 1]));

        $this->assertTrue($status->isInitial());

    }

    private function buildStatus()
    {
        $maintenance_flags_provider = $this->prophesize(MaintenanceFlagsProvider::class);
        $maintenance_log_provider = $this->prophesize(MaintenanceLogProvider::class);
        $next_due_schedule_provider = $this->prophesize(NextDueScheduleProvider::class);
        $component_requirement_properties_provider = $this->prophesize(ComponentRequirementPropertiesProvider::class);

        return new RequirementStatusProvider($maintenance_flags_provider->reveal(), $maintenance_log_provider->reveal(), $next_due_schedule_provider->reveal(), $component_requirement_properties_provider->reveal());
    }
}

这是我正在尝试测试的类/方法的相关部分...

namespace App\Services\Components\Requirements\Status;

use Carbon, StdClass;
use App\Services\Maintenance\Logs\MaintenanceLogProvider;
use App\Services\Maintenance\Flags\MaintenanceFlagsProvider;
use App\Services\Maintenance\NextDueSchedules\NextDueScheduleProvider;
use App\Services\Components\Requirements\Properties\ComponentRequirementPropertiesProvider;

class RequirementStatusProvider
{
    public $maintenance_flags_provider;
    public $maintenance_log_provider;
    public $next_due_schedule_provider;
    public $component_requirement_properties_provider;

    public $data;

    /**
     * @param MaintenanceFlagsProvider $maintenance_flags_provider
     * @param MaintenanceLogProvider $maintenance_log_provider
     * @param NextDueScheduleProvider $next_due_schedule_provider
     * @param ComponentRequirementPropertiesProvider $component_requirement_properties_provider
     */
    public function __construct(MaintenanceFlagsProvider $maintenance_flags_provider, MaintenanceLogProvider $maintenance_log_provider, NextDueScheduleProvider $next_due_schedule_provider, ComponentRequirementPropertiesProvider $component_requirement_properties_provider)
    {
        $this->data = new StdClass();

        $this->maintenance_flags_provider = $maintenance_flags_provider;
        $this->maintenance_log_provider = $maintenance_log_provider;
        $this->next_due_schedule_provider = $next_due_schedule_provider;
        $this->component_requirement_properties_provider = $component_requirement_properties_provider;
    }

// THIS IS WHAT I'M TRYING TO TEST ....
    public function isInitial()
    {
        $flag = $this->maintenance_flags_provider->findMostRecentByLabel('initial', $this->component->id, $this->requirement->id, $this->data->datetime);

        return (($flag && 1 == $flag->getAttribute('value')) || ! $this->data->pcw_logs[0]->event_at) ? 1 : 0;
    }
}

我也通过以下方式修改了测试...

/** @test */
public function is_initial_returns_true()
{
    $maintenance_log_provider = $this->prophesize(MaintenanceLogProvider::class);
    $maintenance_flags_provider = $this->prophesize(MaintenanceFlagsProvider::class);
    $next_due_schedule_provider = $this->prophesize(NextDueScheduleProvider::class);
    $component_requirement_properties_provider = $this->prophesize(ComponentRequirementPropertiesProvider::class);

    $maintenance_flags_provider->findMostRecentByLabel('initial', 1, 1, Carbon::now())->willReturn(new MaintenanceFlag(['value' => 1]));

    $status = new RequirementStatusProvider($maintenance_flags_provider->reveal(), $maintenance_log_provider->reveal(), $next_due_schedule_provider->reveal(), $component_requirement_properties_provider->reveal());

    $this->assertTrue($status->isInitial());
}

即使我省略了 ->willReturn 部分,我仍然会得到完全相同的错误。

我不希望 isInitial 调用实际的 MaintenanceFlagsProvider 类,我希望测试伪造该调用,但通过测试将 $flag 变量设置为我想要的任何值(如果有意义的话)。

【问题讨论】:

  • 似乎问题是我的 MaintenanceFlagsProvider 使用 __call 将方法调用转发到我的存储库。这就是预言的绊脚石。现在我要么需要大规模重组我的项目,要么找到一些解决方法/技巧。

标签: unit-testing laravel mocking phpunit prophecy


【解决方案1】:

部分问题在于我的提供程序将未定义的方法调用转发到相应的存储库类。我可以通过为提供者类添加缺少方法的@method 签名来让 Prophecy 高兴

/**
 * @method findMostRecentByLabel(array $args = [])
 */
class MaintenanceFlagsProvider
{
    ...
}

工作测试...

/** @test */
public function is_initial_returns_true()
{
    $date = Carbon::now();

    $maintenance_log_provider = $this->prophesize(MaintenanceLogProvider::class);
    $maintenance_flags_provider = $this->prophesize(MaintenanceFlagsProvider::class);
    $next_due_schedule_provider = $this->prophesize(NextDueScheduleProvider::class);
    $component_requirement_properties_provider = $this->prophesize(ComponentRequirementPropertiesProvider::class);

    $maintenance_flags_provider->findMostRecentByLabel('initial', 1, 1, $date)->shouldBeCalled()->willReturn(new MaintenanceFlag(['value' => 1]));

    $status = new RequirementStatusProvider($maintenance_flags_provider->reveal(), $maintenance_log_provider->reveal(), $next_due_schedule_provider->reveal(), $component_requirement_properties_provider->reveal());

    $status->component = (new Component())->forceFill(['id' => 1]);
    $status->requirement = (new MaintenanceRequirement())->forceFill(['id' => 1]);
    $status->data->datetime = $date;

    $this->assertTrue($status->isInitial());
}

【讨论】:

    猜你喜欢
    • 2021-12-23
    • 2018-02-08
    • 1970-01-01
    • 2015-07-10
    • 2023-03-14
    • 2020-05-13
    • 2018-03-03
    • 2011-12-26
    • 2012-01-09
    相关资源
    最近更新 更多