Насмешливая стати c Методы в PHP - PullRequest
1 голос
/ 09 марта 2020

Моя цель состоит в том, чтобы иметь возможность писать модульные тесты для методов c, которые поддерживают:

  1. Поддерживаемость - я хочу, чтобы код был таким же простым для понимания, понимания и отладки с течением времени ,
  2. Производительность - я бы хотел, чтобы скорость наших тестов не пострадала из-за технического долга, если это возможно.

Ограничения: Мы не можем изменить метод stati c, чтобы метод экземпляра. Это было бы первым, что я бы, вероятно, предложил, но я ищу варианты / альтернативы и мнения.

Тестирование методов stati c - это немного больно. Было время, когда мы могли сделать это с помощью phpunit. В Mockery есть средства для тестирования stati c методов * от 1012 * до aliasing , но это не рекомендуется. Я обнаружил, что выполнение этих типов тестов может быть очень медленным. (отсюда и цель № 2).

К сожалению, если у вас есть достаточное количество кода, основанного на другом коде с использованием методов stati c, вы можете рассчитывать на собственный долг. Существуют некоторые методики, использующие call_user_func (https://medium.com/@nihon_rafy / методики для моделирования c -методов для юнит-тестов-в-php -18b2a11458d0 ) и forward_static_call_array() (http://miljar.github.io/blog/2014/01/29/phpunit-testing-static-calls/), но мне трудно следовать этому коду.

Я хочу предоставить альтернативную опцию динамического c, аналогичную приведенной выше.

class LegacyClass {
    public static function staticMethod($a, $b, $c) {
        return QueryBuilder::where($a, $b, $c)->getAll();
    }

}

class ClassToTest {
    public function test($a, $b, $c) {
        return LegacyClass::staticMethod($a+1, $b+2, $c+3);

}

изменяется на это =>

class LegacyClass {
    public static function staticMethod($a, $b, $c) {
        return QueryBuilder::where($a, $b, $c)->getAll();
    }

}

class ClassToTest{
    // @var string fully qualified class name
    private $legacyClass = LegacyClass::class;
    public function test($a, $b, $c) {
        return {$this->legacyClass}::staticMethod($a+1, $b+2, $c+3);

}

Теперь, с учетом вышеизложенного, мы можем смоделировать LegacyClass, получить имя класса этого макета и использовать Reflection для установки приватного $legacyClass переменная.

При этом мои вопросы:

  1. Какой из перечисленных выше вариантов является наиболее приемлемым решением?
  2. Существуют ли лучшие альтернативы, которые соответствуют заявленные цели? (Если так, я могу добавить)

Спасибо за ваш вклад!

1 Ответ

0 голосов
/ 10 марта 2020

Решением, к которому я очень часто возвращаюсь, является создание класса «человек посередине». Я использую это для вызовов функции stati c, но также и для случаев, когда в середине кода было создано new Object();.

По сути, вы просто перемещаете проблему куда-то еще, что может показаться не хорошим решением, но вы делаете ClassToTest легко тестируемым, удаляя одну строку.

Итак, вкратце; Я бы сделал новый класс (StaticFunctionCallerClass). Этот класс будет иметь одну функцию с одной строкой.

class StaticFunctionCallerClass {
    public function test($a, $b, $c) {
        return LegacyClass::staticMethod($a+1, $b+2, $c+3);

}

Теперь вы можете создать экземпляр этого класса в своем ClassToTest (и, следовательно, смоделировать его в тесте). Таким образом, вы можете проверить все логи c вокруг него и даже проверить, что ваш новый StaticFunctionCallerClass также вызывается с правильной информацией.

Недостаток здесь в том, что он оставляет ваш новый StaticFunctionCallerClass со строкой трудно проверить код. Вы можете вызвать этот класс в своем LegacyClassTest, чтобы проверить, правильно ли выполнен вызов, что, возможно, не очень чистый вариант, но он действительно выполняет свою работу.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...