Пользовательский механизм сопоставления и / или расширения PhpSpec не работает - PullRequest
1 голос
/ 21 марта 2019

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

Я пробовал это с помощью встроенного сопоставителя, вот так:

public function getMatchers(): array
{
    return [
        'beFinal' => function ($subject) {
            $reflection = new \ReflectionClass($subject);

            if (!$reflection->isFinal()) {
                throw new FailureException('Expected subject to be final, but it is not.');
            }
            return true;
        },
    ];
}

Это работает достаточно хорошо, когда я звоню $this->shouldBeFinal();. Проблема в том, что когда я вызываю $this->shouldNotBeFinal();, он выводит общее сообщение: [obj:Class\To\Test] not expected to beFinal(), but it did. вместо того, которое я хотел бы показать.

Другая проблема в том, что я не хочу этого только для одного класса. Вот почему я решил сделать расширение для него.

Вот что я получил:

phpspec.yml

extensions:
    PhpSpecMatchers\Extension: ~

PhpSpecMatchers / Extension.php :

<?php

declare(strict_types=1);

namespace PhpSpecMatchers;

use PhpSpec\ServiceContainer;
use PhpSpecMatchers\Matchers\BeFinalMatcher;

class Extension implements \PhpSpec\Extension
{
    public function load(ServiceContainer $container, array $params): void
    {
        $container->define(
            'php_spec_matchers.matchers.be_final',
            function ($c) {
                return new BeFinalMatcher();
            },
            ['matchers']
        );
    }
}

PhpSpecMatchers / Matchers / BeFinalMatcher.php

<?php

declare(strict_types=1);

namespace PhpSpecMatchers\Matchers;

use PhpSpec\Exception\Example\FailureException;
use PhpSpec\Matcher\BasicMatcher;

class BeFinalMatcher extends BasicMatcher
{
    public function supports(string $name, $subject, array $arguments): bool
    {
        return $name === 'beFinal';
    }

    public function getPriority(): int
    {
        return 0;
    }

    protected function matches($subject, array $arguments): bool
    {
        $reflection = new \ReflectionClass($subject);

        return $reflection->isFinal();
    }

    protected function getFailureException(string $name, $subject, array $arguments): FailureException
    {
        return new FailureException('Expected subject to not be final, but it is.');
    }

    protected function getNegativeFailureException(string $name, $subject, array $arguments): FailureException
    {
        return new FailureException('Expected subject to be final, but it is not.');
    }
}

Всякий раз, когда я пытаюсь вызвать $this->beFinal(); с этой конфигурацией, спецификация нарушается и показывает следующее сообщение: method [array:2] not found.. Если я добавлю метод isFinal () к классу, который я тестирую, и верну, например, значение true, он принимает значение $this->shouldBeFinal(); и дает сбой для $this->shouldNotBeFinal();, но я не хочу добавлять этот метод , Я должен просто работать без него, и, насколько я понимаю, он должен работать так, верно?

Я также пытался добавить пользовательские наборы в мой phpspec.yml , например:

suites:
    matchers:
        namespace: PhpSpecMatchers\Matchers
        psr4_prefix: PhpSpecMatchers\Matchers
        src_path: src/PhpSpecMatchers/Matchers
        spec_prefix: spec/PhpSpecMathcers/Matchers

Но это ничего не меняет. Я также попытался добавить следующую конфигурацию в phpspec.yml :

extensions:
    PhpSpecMatchers\Extension:
        php_spec_matchers:
        src_path: src
        spec_path: spec

Это тоже ничего не меняет.

Еще одна вещь, которую я попробовал, это отказаться от подхода расширения и просто объявить мой mather в phpspec.yml , вот так:

matchers:
    - PhpSpecMatchers\Matchers\BeFinalMatcher

Как и следовало ожидать: те же результаты.

Загрузка в PhpSpecMatchers \ Extension действительно вызывается (проверяется простым var_dump(…);), но кажется, что она ничего не достигает в PhpSpecMatchers \ Matchers \ BeFinalMatcher , так как я не получаю никакого вывода из любого var_dump(…);

Я следовал учебным пособиям и примерам из symfonycasts, самого phpspec docs и некоторых других проектов github, которые я обнаружил, все они почти идентичны моему коду (за исключением пространств имен, структур каталогов и тому подобного), поэтому я любезен в недоумении здесь.

Как мне добраться до точки, где я могу успешно позвонить $this->shouldBeFinal(); и $this->shouldNotBeFinal();?

Большое спасибо, кто может помочь мне здесь.

P.S .: Я также опубликовал этот выпуск на github phpspec.

1 Ответ

0 голосов
/ 22 марта 2019

Так что, очевидно, приоритет был слишком низким (см. этот комментарий проблема с github моего phpspec). PhpSpec \ Matcher \ IdentityMatcher (откуда берется shouldBe) простирается от PhpSpec \ Matcher \ BasicMatcher , где приоритет установлен на 100. Так как мой был установлен в 0, он сначала попал в мой (я думаю) и поэтому не выполнялся должным образом. Я установил свой приоритет на 101, и он работает безупречно (за исключением того, что я переключил положительные и отрицательные сообщения, я узнал).

...