Laravel 8 如何从单元测试数据提供者中使用工厂状态?(从 Laravel 7 迁移)

3
在 Laravel 7 中,我们经常使用以下模式:
public function provideCanDoThing(): array
{
    return [
        "Root can do thing" => [['root'], true],
        "Normal user cannot do thing" => [[], false],
        "Root cannot do thing while suspended" => [['root', 'suspended'], false],
    ];
}

/**
  * @dataProvider provideCanDoThing
  */
public function testCanDoThing(array $userStates, bool $expectedCanDo): void
{
    $user = factory(User::class)->states($userStates)->create();
    self::expectSame($expectedCanDo, $user->canDoThing());
}

状态 "root" 可以相当复杂,具有属性和 afterCreating 逻辑的组合。

在新的 Laravel 8 工厂中,state 方法不再在命名状态下运行收集的更改,而是像传递属性给 makecreate 一样工作?

我可以看到如何重写测试,更像:

$userFactory = User::factory();
foreach($userStates as $userState){
    $userFactory = $userFactory->{$userState}();
}
$user = $userFactory->create();

但这似乎表达能力较弱。我想我很惊讶我找不到一个在Factory上为我完成这个任务的方法。

1个回答

1
似乎当更多人将其工厂和测试迁移到Laravel 8时,解决此问题将受到高度需求。
我在一个trait中编写了这个解决方案,可以由工厂使用:
<?php

namespace App\Traits;

use Illuminate\Database\Eloquent\Factories\Factory;
use Illuminate\Support\Arr;

trait FactoryApplyStates
{
    /**
     * Applies one or more states to a model factory
     *
     * @param string|array $stateMethods
     * @return Factory
     * @throws \Exception
     */
    public function applyStates($stateMethods = null)
    {
        $stateMethods = Arr::wrap($stateMethods);

        $factory = $this;
        /* @var Factory $factory */

        foreach ($stateMethods as $stateMethod) {
            if (is_callable($stateMethod)) {
                $factory = $stateMethod($factory);
            } else {
                if (!is_string($stateMethod)) {
                    throw new \Exception('Incorrect state name: must be a name of method');
                }
                if (!method_exists($this, $stateMethod)) {
                    throw new \Exception('Unsupported state for ' . __CLASS__ . ': ' . $stateMethod . '() method does not exist');
                }
                $factory = $factory->{$stateMethod}();
            }
        }

        return $factory;
    }
}


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接