PHPUnit - вызывается метод признака Assert - PullRequest
0 голосов
/ 04 июля 2019

Предположим, у меня есть черта, у которой в настоящее время есть метод:

trait MyTrait
{
    public function traitMethod()
    {
        return true;
    }
}

Теперь предположим, что эта черта используется несколькими классами, но я не хочу писать модульный тест для каждого класса.Вместо этого я хочу написать один модульный тест только для черты:

public function testTraitMethod()
{
    $trait = $this->getMockForTrait(MyTrait::class);
    $this->assertTrue($trait->traitMethod());
}

Но проблема в том, что класс может переопределить метод черты:

class MyClass
{
    use MyTrait;

    public function traitMethod()
    {
        return false;
    }
}

В этом случае MyClass делает что-то не так, но я не знаю об этом, так как я тестирую только черту.

Моя идея - написать отдельный модульный тест для каждого класса, просто чтобы проверить, использует ли он эту чертуи это не отменяет этот метод.Если класс должен переопределить метод trait, тогда ему также нужен специальный юнит-тест.

В настоящее время я пишу юнит-тесты для каждого класса, который реализует мою черту, но это, конечно, тесты копирования-вставкиповсюду.

Так есть ли способ проверить, вызывает ли класс свой метод черты?

1 Ответ

0 голосов
/ 05 июля 2019

Я нашел решение, используя Reflection, я опубликую его на случай, если кому-то понадобится, потому что я не смог найти ничего, связанного с моей проблемой.Не стесняйтесь комментировать или добавлять различные решения, если хотите.

Так что следующий тест утверждает, что $serviceClass использует $traitClass и не переопределяет методы, объявленные в $traitClass, кроме абстрактных и тех, которые вручнуюдобавлен в массив $overriddenMethods.

public function testServiceUsesTrait()
{
    $serviceClass = MyClass::class;
    $traitClass = MyTrait::class;

    $this->assertContains($traitClass, (new \ReflectionClass($serviceClass))->getTraitNames());

    $reflectedTrait = new \ReflectionClass($traitClass);
    $reflectedTraitFile = $reflectedTrait->getFileName();

    /**
     * If $serviceClass overrides some trait methods they
     * should be inserted into this array to avoid test failure.
     * Additional unit-tests should be written for overridden methods.
     */
    $overriddenMethods = [];

    foreach ($reflectedTrait->getMethods() as $traitMethod) {
        if ($traitMethod->isAbstract() || in_array($traitMethod->getName(), $overriddenMethods, true)) {
            continue;
        }
        $classMethod = new \ReflectionMethod($serviceClass, $traitMethod->getName());
        $this->assertSame($reflectedTraitFile, $classMethod->getFileName(), sprintf(
            'Trait method "%s" is overridden in class "%s" thus it must be excluded from this test.',
            $traitMethod->getName(), $serviceClass
        ));
    }
}

Я также попытался сравнить объявление классов, используя $classMethod->getDeclaringClass() вместо сравнения имен файлов, но это не сработало: даже если метод trait не переопределен в классе, getDeclaringClass() всегда возвращает сам класс.

...