Ответ 1
Проблема заключается не в том, чтобы окупить метод, а в ваш класс.
Вы выполняете работу в конструкторе. Чтобы установить объект в состояние, вы извлекаете удаленный файл. Но этот шаг не требуется, поскольку объект не нуждается в том, чтобы данные находились в правильном состоянии. Вам не нужен результат из файла, прежде чем вы назовете getFormatted
.
Вы можете отложить загрузку:
class ClassA {
private $dog;
private $formatted;
public function __construct($param1) {
$this->dog = $param1;
}
protected getResultFromRemoteServer() {
if (!$this->formatted) {
$this->formatted = file_get_contents(
'http://whatever.com/index.php?' . $this->dog
);
}
return $this->formatted;
}
public getFormatted() {
return ("The dog is a " . $this->getResultFromRemoteServer());
}
}
чтобы вы лениво загружали удаленный доступ, когда он действительно нужен. Теперь вам вообще не нужно заглушать getResultFromRemoteServer
, но вместо этого можно заглушить getFormatted
. Вам также не нужно будет открывать ваш API для тестирования и публиковать getResultFromRemoteServer
public.
В боковом указателе, даже если это всего лишь пример, я переписал бы этот класс для чтения
class DogFinder
{
protected $lookupUri;
protected $cache = array();
public function __construct($lookupUri)
{
$this->lookupUri = $lookupUri;
}
protected function findById($dog)
{
if (!isset($this->cache[$dog])) {
$this->cache[$dog] = file_get_contents(
urlencode($this->lookupUri . $dog)
);
}
return $this->cache[$id];
}
public function getFormatted($dog, $format = 'This is a %s')
{
return sprintf($format, $this->findById($dog));
}
}
Поскольку это Finder, теперь может иметь смысл иметь findById
public сейчас. Просто держите его в безопасности, потому что это то, что у вас было в вашем примере.
Другим вариантом будет расширение Subject-Under-Test и замена метода getResultFromRemoteServer
вашей собственной реализацией, возвращающей Poodle
. Это означает, что вы не тестируете фактический ClassA
, а подкласс ClassA
, но это то, что происходит, когда вы используете Mock API в любом случае.
Как и в случае с PHP7, вы можете использовать класс анонимного типа:
public function testPoodle() {
$stub = new class('dog52') extends ClassA {
public function getResultFromRemoteServer() {
return 'Poodle';
}
};
$expected = 'This dog is a Poodle';
$actual = $stub->getFormatted();
$this->assertEquals($expected, $actual);
}
Перед PHP7 вы просто напишите обычный класс, расширяющий тему-под-Тест, и используйте это вместо Subject-Under-Test. Или используйте disableOriginalConstructor
, как показано в другом месте на этой странице.