Comments 10
Подход вида:
в корне не верен. Потому и тестировать сложно. По-хорошему нужно вызывать не глубже одного метода из инкапсулированного объекта, а в нем уже проксировать запрос дальше. В таком случае при тесте достаточно мокнуть инкапсулируемый объект без усложнения себе жизни
public function get_friends(){
$friends = $this->home_tree->num_squirrels;
$friends += $this->home_tree->forest->num_animals('bunny'));
return $friends;
}
в корне не верен. Потому и тестировать сложно. По-хорошему нужно вызывать не глубже одного метода из инкапсулированного объекта, а в нем уже проксировать запрос дальше. В таком случае при тесте достаточно мокнуть инкапсулируемый объект без усложнения себе жизни
+2
… при этом тролили меня на реддите с AspectMock :)
Ваш код будет работать ровно до того момента пока мы явно не укажем класс для требуемых зависимостей:
Ничего нет сложного, чтобы создать из массива обьект, а вот заставить этот обьект полностью вести себя как экземпляр некого класса, это уже задача гораздо сложнее.
Ваш код будет работать ровно до того момента пока мы явно не укажем класс для требуемых зависимостей:
public function __construct($name, Tree $home_tree)
Ничего нет сложного, чтобы создать из массива обьект, а вот заставить этот обьект полностью вести себя как экземпляр некого класса, это уже задача гораздо сложнее.
0
>Иногда случаются случаи когда тестируемый метод использует глубокие проперти объекта например:
есть такое правило в XP и вообще в TDD, и правильном OOP, что не стоит внутри какого-либо объекта обращаться к свойствам «глубиной» больше чем в 1 вызов, т.е. в вашем случае
>$this->home_tree->forest->num_animals('bunny'));
должно быть как-то так
>$this->home_tree->numAnimalsInForest('bunny');
либо использовать AspectMock, т.к. с ним гораздо проще это сделать, чем кастовать как вы показали, т.к. у вас все таки нечитаемо, либо еще один вариат: перенести тест из разряда Unit в разряд Functional/Endtoend и нормально протестировать взаимодействие нескольких компонентов, а то вы можете в один прекрасный день просто закончить тестированием моков и все, тесты будут проходить а код валиться.
P.S. вижу тут уже заметили что я хотел сказать:
>По-хорошему нужно вызывать не глубже одного метода из инкапсулированного объекта
:)
есть такое правило в XP и вообще в TDD, и правильном OOP, что не стоит внутри какого-либо объекта обращаться к свойствам «глубиной» больше чем в 1 вызов, т.е. в вашем случае
>$this->home_tree->forest->num_animals('bunny'));
должно быть как-то так
>$this->home_tree->numAnimalsInForest('bunny');
либо использовать AspectMock, т.к. с ним гораздо проще это сделать, чем кастовать как вы показали, т.к. у вас все таки нечитаемо, либо еще один вариат: перенести тест из разряда Unit в разряд Functional/Endtoend и нормально протестировать взаимодействие нескольких компонентов, а то вы можете в один прекрасный день просто закончить тестированием моков и все, тесты будут проходить а код валиться.
P.S. вижу тут уже заметили что я хотел сказать:
>По-хорошему нужно вызывать не глубже одного метода из инкапсулированного объекта
:)
+1
Нечитаемо? А как Aspect Mock получилось б проще? Как?
0
дак вы почитайте документацию то ;) у вас на кастование ушло куча (отностительно) строк кода и тест стал менее читабелен, вместо этого могли лишь раз сделать test::double('ForestClass',['num_animals'=>'bunny']); и все, ваш мок готов. не забудьте только чистить в setUp() и в tearDown(). одна строчка кода и то понятная вместо тех 8-10 с каким-то «магическим» кастованием :)
AOP жеж)
AOP жеж)
0
UFO just landed and posted this here
Sign up to leave a comment.
Sylph: Глубокие Stub-ы для тестов от создателей PHPixie, или как конвертировать массив в класс