Продолжу прошлый пост о юнит-тестировании внутренних методов — я чуть усовершенствовал конструкцию
Итак, вначале я пишу тест-кейс наследую PHPUnit_Framework_TestCase. Потом я include’жу тестируемый класс. Инициализирую его в $this->object внутри тест кейса. Теперь, если в тестируемом объекте есть какой-то метод нафаршированный внутренними вызовами, которые мне мешают (например под-запросы в БД и тп.), то я могу их обрубить перезаписью методов на лету с runkit.
Скажем метод
function makePain(){
$foot = $this->getFootFromDB();
$shootingResults = $this->shootAt($foot);
return ($shootingResults["screams"]>5)
}
У меня тестируется так
/**
* @test
*/
function makePain(){
$this->mockMethodRewrite('getFootFromDB', function () {
return array('james bonds foot', 45);
});
$this->assertTrue($this->object->makePain());
}
В данном случае настоящий код getFootFromDB перезаписывается на callable который я предоставляю. Внутри анонимная функция конвертируется в строку и передаётся в runkit. Конвертацию смотрите на stackoverflow.
А сделан он так..
/**
* Rewrites method code to support mocking of private/protected and just internal method calls
*
* @param string $method .
* @param string $method_code .
* @param bool $class .
*/
public function mockMethodRewrite($method, $method_code, $class = false) {
$codeToPassToRunkit = CallableStringifier::stringify($method_code);
runkit_method_redefine(
$class ? $class : get_class($this->object),
$method, //ReflectionFunction::export($method_code, true),
'',
$codeToPassToRunkit,
RUNKIT_ACC_PUBLIC
);
}