Выполнение модульного тестирования с вложенными зависимостями и фабричными классами

Я новичок в модульном тестировании и PHPUnit, но в последнее время я много читал о шаблонах проектирования и изолированных тестах, и я решил провести рефакторинг приложения, которое я Я работаю над тем, чтобы избавиться от статических классов, синглетонов, жестко закодированных зависимостей и всего остального, определенного в глобальной области видимости, надеюсь, что это станет «тестируемым», а не занозой в заднице в будущем, поскольку это должно быть долгосрочный проект.

До сих пор я полагал, что понимаю теорию модульного тестирования, но мне было интересно, в сценарии, когда кто-то делегирует обработку вложенных зависимостей объектов Фабрике, как следует проводить модульное тестирование указанной Фабрики, или это просто избыточно? проверить это? И как лучше всего проверить, что «цепочка» зависимостей работает синхронно?

Позвольте мне проиллюстрировать вопросы. Предположим, у вас есть следующий «устаревший» код:

class House {
    protected $material;
    protected $door;
    protected $knob;

    public function __construct() {
        $this->door = new Door();
        $this->knob = $this->door->getKnob();
        $this->material = "stone";

        echo "House material: ".$this->material. PHP_EOL. "<br/>";
        echo "Door material: ".$this->door->getMaterial(). PHP_EOL. "<br/>";
        echo "Knob material: ".$this->knob->getMaterial(). PHP_EOL. "<br/>";
    }
}

class Door {
    protected $material;
    protected $knob;

    public function __construct() {
        $this->knob = new Knob();
        $this->material = "wood";
    }

    public function getKnob() {
        return $this->knob;
    }

    public function getMaterial () {
        return $this->material;
    }

}

class Knob {
    protected $material;

    public function __construct() {
        $this->material = "metal";
    }

    public function getMaterial () {
        return $this->material;
    }
}

$house = new House();

Это (насколько я понимаю)плохо подходит для модульного тестирования, поэтому мы заменяем жестко заданные зависимости на DI + класс Factory:

class House {
    protected $material;
    protected $door;
    protected $knob;

    public function __construct($door) {
        $this->door = $door;
        $this->knob = $this->door->getKnob();
        $this->material = "stone";

        echo "House material: ".$this->material. PHP_EOL. "<br/>";
        echo "Door material: ".$this->door->getMaterial(). PHP_EOL. "<br/>";
        echo "Knob material: ".$this->knob->getMaterial(). PHP_EOL. "<br/>";
    }
}

class Door {
    protected $material;
    protected $knob;

    public function __construct($knob) {
        $this->knob = $knob;
        $this->material = "wood";
    }

    public function getKnob() {
        return $this->knob;
    }

    public function getMaterial () {
        return $this->material;
    }

}

class Knob {
    protected $material;

    public function __construct() {
        $this->material = "metal";
    }

    public function getMaterial () {
        return $this->material;
    }
}

class HouseFactory {
    public function create() {
        $knob = new Knob();
        $door = new Door($knob);
        $house = new House($door);

        return $house;
    }
}

$houseFactory = new HouseFactory();
$house = $houseFactory->create();

Теперь (и опять же, насколько я понимаю,)House, Door и Knob можно прекрасно протестировать с помощью фиктивных зависимостей. Но:

1)Что теперь происходит с HouseFactory?

Следует ли просто:

  • Не тестировать его, поскольку у него еще нет логики приложения, которую стоит тестировать, а Фабрики обычно остаются такими. Предположим, что если независимые тесты для House, Door & Knob пройдены, Factory должна быть в порядке.
  • Рефакторинг фабрики каким-то образом, т. е. использование функций внутри класса для получения каждого экземпляра таким образом, чтобы можно было переопределить эти функции через PHPUnit для возврата фиктивных объектов, просто на случай, если в классе есть какая-то дополнительная логика, которую можно было бы использовать. некоторые испытания в будущем.

2)Можно ли настроить тесты, основанные на нескольких (не имитируемых)зависимостях одновременно? Я понимаю, что технически это не модульное тестирование, (возможно, интеграционное тестирование? ), но я думаю, что это все еще вполне выполнимо с использованием PHPUnit? Учитывая приведенный выше пример, я хотел бы иметь возможность настроить тест, который не только проверяет House, Door, Knob и HouseFactory изолированно, но и результаты взаимодействия реальных объектов друг с другом, возможно, с некоторыми их имитируемые функции, например те, которые имеют дело с данными. Является ли PHPUnit плохим выбором для такого рода тестов?

Заранее спасибо за внимание. Я понимаю, что некоторые из моих предположений могут быть неверны, поскольку я, очевидно, не эксперт в этом вопросе; исправления приветствуются и приветствуются.

16
задан Mahn 12 April 2012 в 17:43
поделиться