Добавление интерфейса для макета с помощью Mockery (жесткая зависимость) - PullRequest
0 голосов
/ 14 сентября 2018

Мне нужно смоделировать CurrencyEnum, перегрузив его, но это не конец, потому что мне нужно добавить интерфейс к этому макету. Это не работает:

Mockery::mock('overload:'.CurrencyEnum::class);

Ошибка: (..) must be an instance of \BaseCurrency, instance of \CurrencyEnum given. Я посмотрел на Mockery\Container::mock и понятия не имею, как это сделать. В примере я хочу проверить TestingClass::first() метод

class CurrencyEnum implements BaseCurrency
{
    /* methods */
}


class TestingClass
{
    public function first(string $currencySymbol)
    {
        $abc = 'some_string';

        return $this->second($abc, new CurrencyEnum($currencySymbol));
    }

    private function second(string $abc, BaseCurrency $currency)
    {
        /* code */
    }
}

1 Ответ

0 голосов
/ 23 сентября 2018

Метод перегрузки работает, перехватывая механизм autoload: он регистрирует автозагрузчик для класса overloaded, загружая макетированную версию класса вместо оригинала.По умолчанию, он не добавляет много вещей в проверяемый класс.Однако вы можете настроить практически все, что вам может понадобиться.

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

$mock = Mockery::mock('MyClass, MyInterface, OtherInterface');

Из-за способа установки метода Mockery::mock это не будет работать.( Автор приносит свои извинения в исходном коде )

Однако мы можем передать интерфейс (ы) в качестве второго аргумента методу-методу:

Mockery::mock('overload:'.CurrencyEnum::class, BaseCurrency::class);

Это будетзаставить MockConfigurationBuilder добавить BaseCurrency в качестве цели;так как это интерфейс, он заставит макет реализовывать интерфейс.

Альтернативным обозначением вышеизложенного было бы непосредственное использование компоновщика:

Mockery::mock(
    (new MockConfigurationBuilder())
        ->setInstanceMock(true)
        ->setName(CurrencyEnum::class)
        ->addTarget('stdClass')
        ->addTarget(BaseCurrency::class)
)

Сказав, что это, как известно, плохопрактиковаться, чтобы высмеивать такие вещи, как перечисления и объекты значения.Почему бы просто не использовать фактический CurrencyEnum?Что-то такое простое, как код валюты, не совсем оправдывает насмешки.Вероятно, есть структурное улучшение, которое одновременно добавит тонны ценности к вашим тестам и сделает их проще для чтения.

...