Переопределить родительскую функцию в заглушке - PullRequest
1 голос
/ 25 мая 2011

Это, наверное, легко для некоторых из вас. Я пытаюсь проверить защищенный метод на небольшом классе соединения с БД, который у меня есть.

Соответствующий код выглядит следующим образом:

class DbConnect{

/**
 *    Connexion  MSSQL local
 */
protected function localConnect($localconfig){
    $connectionInfo = array("UID" => $localconfig->uid, 
                            "PWD" =>$localconfig->pwd, 
                            "Database"=> $localconfig->DB);

   $this->localConnection = sqlsrv_connect($localconfig->serverName,
                                           $connectionInfo);

   if( $this->localConnection === false ){
       $sql_error = sqlsrv_errors();
       throw new DBException("Error in DB Connection.\r\n
                              SQL ERROR:" . $sql_error);
   }
}
}

Чтобы протестировать метод, у меня была блестящая идея (вероятно, из какого-то поста здесь) подкласс и вызов оттуда. Я создал подкласс, прямо в нижней части моего тестового файла. Я, очевидно, не мог переопределить видимость метода для public, поэтому решил использовать другой подход в заглушке: объявить открытый метод, который вызывает защищенный родительский метод localConnect:

 class DBConnectStub extends DBconnect{

   public function callLocalConnect($localConfig){
        parent::localConnect($localConfig);
    }
}

Мой тест теперь выглядит так:

/**
 * @expectedException DBException
 */
public function test_localConnectError(){

  $localconfig = (object) array ( 'serverName' => 'nohost', 
                                   'uid' => 'nouid',
                                  'pwd' => 'noPwd',
                                  'DB' => 'noDB'

                         );  

  $db = DbConnectStub::getInstance($localconfig, array());
  $db->callLocalConnect($localConfig);
  unset($db);

}

Странная часть, когда я запускаю тест, php выплевывает:

Неустранимая ошибка: вызов неопределенного метода DbConnect :: callLocalConnect () в C: \ tyrelinkCRMsync \ test \ tirelinkCRMSync \ DBConnectTest.php в строке 82.

Объект правильно создан, но почему метод не определен, конечно, есть деталь, которая ускользнула от меня. Этот подход действителен или есть лучший способ?

Ответы [ 2 ]

3 голосов
/ 25 мая 2011

Я пытаюсь проверить защищенный метод [...]

НЕ

Это так просто.Просто не надо.Защищенные методы не являются частью открытого API классов, и поэтому вам не следует делать предположения о том, как они работают, пытаясь убедиться, что ваш класс работает.

Вы должны иметь возможность изменять свой код (реализацию ваших общедоступных функций) без адаптации ваших тестов. Это то, для чего ваши тесты сделаны , так что вы можетеизмените свой код, и вы уверены, что он все еще работает.Вы не можете быть уверены, что ваш код по-прежнему работает, как раньше, когда вы одновременно изменяете свой код и свои тесты!

См .: Sebastian Bergmann -Testing Your Privates.html

Итак: То, что тестирование защищенных и закрытых атрибутов и методов возможно, не означает, что это "хорошая вещь".

и: Best practices to test protected methods with PHPUnit - on abstract classes

В этом посте также упоминается только использование

$method = new ReflectionMethod(
    'Foo', 'doSomethingPrivate'
);
$method->setAccessible(TRUE);

Что проще, чем создание подкласса для каждого метода, который вы хотите протестировать.


Педантичный боковой узел:

Имхо, это должно быть $this->localConnect, а не parent::localConnect, потому что parent :: предназначен только для вызова того же метода родительского класса.(По крайней мере, для меня это не имеет большого значения, просто сбивает с толку).

0 голосов
/ 25 мая 2011

Это может быть глупый вопрос, но вы переопределили DbConnectStub :: getInstance, чтобы он возвращал экземпляр Stub?

class DBConnectStub extends DBconnect{
 public static function getInstance ()
 {
    //whatever process to create the instance (and not the parent method call that will return a DBConnect instance)
 } 

 public function callLocalConnect($localConfig){
    parent::localConnect($localConfig);
 }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...