а так можно? protected, на то он и protected, чтоб был доступен только потомкам.А в тесткейсе наследовать тестируемый класс и сделать protected методы public по каким причинам 'попахивает' ?
class Myclass {
...
public run(){
$this->_run1();
$this->_run2();
}
private _run1(){}
private _run2(){}
/* вводим временные методы */
public tmpRun1{
return $this->_run1();
}
public tmpRun2{
return $this->_run2();
}
}
Для протектед методов еще проще:написать скрипт, который:
1. скопирует файл в безопасное место
2. сделает этот метод паблик
3. протестирует его так, как если бы это был паблик метод
+1Имхо тестировать надо не классы, а интерфейсы. Поэтому ты не должен этого хотеть.
Может быть, "жадный тест"?имхо, как правило запахом 'жадные методы'
public function testPayout(){
...
$o = $this->getMock('PSO_LibertyReserve_Operator',
Array('createPayoutRequest','doRequest',
'analyseLrResponse','parseOperations'));
...
$o->expects($this->once())
->method('doRequest')
->will($this->returnValue('<bar></bar>'));
...
$this->assertTrue($o->payout($p,$acc));
}
public function testGetBalance(){
...
$o = $this->getMock('PSO_LibertyReserve_Operator',
Array('createBalanceRequest','doRequest',
'analyseLrResponse','parseBalance'));
...
$o->expects($this->once())
->method('doRequest')
->will($this->returnValue('<bar></bar>'));
...
$amount = $o->getBalance($acc);
$this->assertEquals(100500,$amount);
}
public function testSearchSubrequest(){
...
$o->expects($this->once())
->method('doRequest')
->will($this->returnValue('<foo></foo>'));
...
}
interface PSO_IOperator {
public function payout(PSO_IPayment $payment,$account);
public function getBalance($account,$force=false);
public function search(PSO_ISearchCriteria $criteria,$account);
}
Из приведенного кода не очевидно, что закрытые методы тестировать надо. Смысл модульного тестирования - проверить, что класс правильно реагируют на внешнее воздействие.Автор оригинала: whirlwind
Объясняю на пальцах почему нужно тестировать закрытые методы и почему эта ситуация частая
Вот 3 теста
Метод doRequest должен быть защищенным, потому что это внутренности. Интерфес имплементируется следующийPHP:... public function testGetBalance(){ ... $o = $this->getMock('PSO_LibertyReserve_Operator', Array('createBalanceRequest','doRequest', 'analyseLrResponse','parseBalance')); ... $o->expects($this->once()) ->method('doRequest') ->will($this->returnValue('<bar></bar>')); ... $amount = $o->getBalance($acc); $this->assertEquals(100500,$amount); } ...
То есть, остальные методы лучше всего скрыть, т.к. они загрязняют интерфейс. Если вы способны реализовать этот интерфейс через TDD без защищенных методов и без дублирования кода, тогда остается только снять шляпу и пасть ниц. У меня в классе получилось 26 методов всего, из которых только 3 должны быть паблик.PHP:interface PSO_IOperator { public function payout(PSO_IPayment $payment,$account); public function getBalance($account,$force=false); public function search(PSO_ISearchCriteria $criteria,$account); }
interface PSO_IOperator {
public function payout(PSO_IPayment $payment,$account);
public function getBalance($account,$force=false);
public function search(PSO_ISearchCriteria $criteria,$account);
public function setRequestHandler(RequestHandlerInterface $handler) {
}
class PSO_LibertyReserve_Operator implements PSO_IOperator {
/**
* @var RequestHandlerInterface
*/
private $requestHandler;
public function getBalance($account,$force=false) {
...
$requestResult = $this->requestHandler->doRequest();
...
}
}
public function testGetBalance() {
//fixture
$requestMock = $this->getMock('RequestHandlerInterface');
$requestMock->expects($this->once())
->method('doRequest')
->will($this->returnValue('<bar></bar>'));
$operator = new PSO_LibertyReserve_Operator();
$operator->setRequestHandler($requestMock);
//exercise
$operator->getBalance($acc);
}
Я не знаю, что такое модульное тестирование в твоем понимании. В теме стоит TDD - Test-Driven Development. Разработка на основе тестов, а не тестирование уже написанного. Разницу чуешь?Смысл модульного тестирования - проверить, что класс правильно реагируют на внешнее воздействие.
С чего ты взял что лучше? Этот метод был введен намеренно, для того что бы избавиться от зависимости транспортного уровня в тестах, которые никакого отношения к этому самому транспорту не имеют. Где в коде видно, что в работе не используется впрыск зависимого объекта? Стабы для того и придумали, что бы не заморачиваться эмулированием всей необходимой фикстуры а просто настроить 1 метод.Судя по имени функции, которую ты подменяешь (doRequest), она получает результат откуда-то извне (запрос к БД, curl, ....). В этом случае лучше лучше сделать инверсию зависимостей, вынести функционал по обращению к внешнему ресурсу в отдельный класс, а уже при тестировании этот класс подменять.
То есть для тебя не очевидно, что метод, который в самом элементарном примере вызывается 3 раза должен быть протестирован? Это не говоря о том, что по TDD сначала появляется тест, а уже потом метод.Из приведенного кода не очевидно, что закрытые методы тестировать надо
Это не разговор. Нет не чую, объясни.Разницу чуешь?
Вот именно. Так как у тебя мог появиться метод doRequest(), до того как появились методы payout(), getBalance() и search()? Ведь реализация класса начинается именно с этих методов. Похоже, это ты занимаешься "тестированием уже написанного" кода.Это не говоря о том, что по TDD сначала появляется тест, а уже потом метод.
А при чём здесь количество вызовов методов. Это у тебя такой подход к тестированию? Должен тебя огорчить, ты не понял смысла TDD, так как, скорее всего, не писал тесты до написания кода.То есть для тебя не очевидно, что метод, который в самом элементарном примере вызывается 3 раза должен быть протестирован?