Пока ОП спрашивал об общей проблеме, а не спрашивал, как улучшить его конкретный код - я постараюсь ответить, используя некоторые абстрактные и крошечные классы:
Что ж, тестирование не сложнеесами статические методы, но труднее протестировать методы, использующие статические методы.
Давайте рассмотрим разницу на небольшом примере.
Допустим, у нас есть класс
class A
{
public static function weird()
{
return 'some things that depends on 3rd party resource, like Facebook API';
}
}
Он выполняет некоторую работу, которая требует настройки дополнительной среды (в данном случае с указанием ключей API) и подключения к Интернету для служб API FB.Тестирование этого метода займет некоторое время (только из-за задержек в сети и API), но его достаточно просто протестировать.
Теперь мы реализуем класс, который использует метод A::weird()
:
class TestMe
{
public function methodYouNeedToTest()
{
$data = A::weird();
return 'do something with $data and return';
}
}
Пока - мы не можем протестировать TestMe::methodYouNeedToTest()
без дополнительных шагов, необходимых для работы A::weird()
.Да, вместо тестирования methodYouNeedToTest
нам также нужно делать вещи, которые не связаны напрямую с этим классом, а с другим.
Если мы пошли другим путем с самого начала:
class B implements IDataSource
{
public function weird()
{
return 'some things that depends on 3rd party resource, like Facebook API';
}
}
вы видите - ключевое отличие здесь в том, что мы реализовали интерфейс IDataSource
и сделали метод нормальным, а не статическим.Пока что мы могли бы переписать наш код выше таким образом:
class TestMe
{
public function methodYouNeedToTest(IDataSource $ds)
{
$data = $ds->weird();
return 'do something with $data and return';
}
}
И теперь мы не полагаемся на конкретную реализацию, а делаем на интерфейс.И теперь мы можем легко смоделировать источник данных.
Такие абстракции помогают сосредоточить наши тесты больше на самом тестировании, а не на создании необходимой среды.
Такие шаги помогают нам иметь наш блоктесты быстро.Хотя у нас все еще могут быть приемочные, нагрузочные и функциональные тесты (но это уже другая история), которые проверяют, что наше приложение работает как положено