Использование @dataProvider в абстрактном базовом классе с реализацией в реальном тесте - PullRequest
0 голосов
/ 23 января 2020

Я пытаюсь создать базовый класс для тестирования правил проверки из Laravel, хотя то, что тестируется, на самом деле не является проблемой в этом случае.

Вот что я сделал:

<?php

namespace Tests\Unit\Rules;

use Tests\TestCase;
use Illuminate\Contracts\Validation\Rule;

abstract class RuleTestCase extends TestCase
{
    protected Rule $rule;

    public function setUp(): void
    {
        parent::setUp();

        $this->rule = $this->initializeRule();
    }

    /**
     * @dataProvider validRuleInput
     *
     * @param mixed $value
     */
    public function testRuleWithValidInput($value): void
    {
        $this->assertTrue($this->rule->passes('attribute', $value));
    }

    /**
     * @dataProvider invalidRuleInput
     *
     * @param mixed $value
     */
    public function testRuleWithInvalidInput($value): void
    {
        $this->assertFalse($this->rule->passes('attribute', $value));
    }

    abstract public function validRuleInput(): array;

    abstract public function invalidRuleInput(): array;

    abstract public function initializeRule(): Rule;
}

И вот как я хотел бы реализовать это:

<?php

namespace Tests\Unit\Rules\Text;

use App\Rules\Text\ContainsLetters;
use Illuminate\Contracts\Validation\Rule;
use Tests\Unit\Rules\RuleTestCase;

class ContainsLettersTest extends RuleTestCase
{
    public function validRuleInput(): array
    {
        return [
            'abcd',
            'a2c4',
            '!b#d',
        ];
    }

    public function invalidRuleInput(): array
    {
        return [
            '1234',
            '!@#$',
            '1@3$',
        ];
    }

    public function initializeRule(): Rule
    {
        return new ContainsLetters;
    }
}

Я ожидал бы, что это сработает, поскольку поставщики данных реализованы в тестируемом классе, хотя фактический метод тестирования реализован в абстрактном базовом классе.

При выполнении phpunit я получаю следующее предупреждение:

1) Warning
The data provider specified for Tests\Unit\Rules\Text\ContainsLettersTest::testRuleWithValidInput is invalid.
Data set #0 is invalid.

Это говорит мне о том, что тестовый метод в абстрактном базовом классе может быть выполнен, но не может разрешить реализация поставщиков данных.

Я не уверен, как решить эту проблему и / или если это можно решить. Я попытался:

  • Гуглить, это вывело это , которое кажется чем-то связанным, но похоже, что это было исправлено / разрешено долгое время go
  • Попытка добавить @dataProvider static::validRuleInput (после изменения validRuleInput на public abstract static метод

Я бы хотел, чтобы в моих тестовых примерах было как можно меньше шаблонов, и это, кажется, отличный способ для достижения так как все классы правил выполняют проверку некоторых входных данных и не нуждаются в предварительных тестах, и я хотел бы, чтобы в каждом тесте не было всех тестовых образцов, подтверждающих это, но основное внимание уделялось тестируемому правилу и данным, которые должны быть (в) действителен. Если есть лучший способ сделать это, я, конечно, все уши.

Версии: PHPUnit 8.5.2 & PHP 7.4.0

1 Ответ

1 голос
/ 23 января 2020

Вы должны возвращать для каждого тестового примера список значений, которые будут переданы в качестве аргументов в тестовый метод. Итак:

return [
    [ // <-- first test case
        '1st_argument_value',
        '2nd_argument_value',
    ],
    [ // <-- second test case
        '1st_argument_value',
        '2nd_argument_value',
    ],
];

Если вместо этого использовать yield, это будет более понятным:

yield [ // <-- first test case
    '1st_argument_value',
    '2nd_argument_value',
];

yield [ // <-- second test case
    '1st_argument_value',
    '2nd_argument_value',
];
...