У меня есть очень простой класс, как этот ниже:
abstract class Person
{
private $id;
private $createdOn;
// ... More private properties
protected $unfound = array();
Конструктор выполняет foreach для переданного массива $ data и, используя правильные методы, присваивает значения свойствам.
Если метод не существует, то ключ добавляется в защищенный массив, чтобы сохранить его след (я назвал его $ unound, просто чтобы быть оригинальным!).
public function __construct($data)
{
foreach ($data as $field => $value)
{
$method = 'set' . ucfirst($field);
if (method_exists($this, $method))
{
$this->$method($value);
}
else
{
$this->unfound[] = $field;
}
}
}
Список методов для установки значений для свойств
public function setId($id) {
$this->id = $id;
}
public function setCreatedOn($createdOn) {
$this->createdOn = $createdOn;
}
И список методов, чтобы получить эти назначенные значения
public function getId() {
return $this->id;
}
public function getCreatedOn() {
return $this->createdOn;
}
} // END of the class
Как видите, класс не выполняет никаких сложных задач: он принимает массив
array(
'id' => 4,
'createdOn' => '2015-01-07 20:50:00',
'unknownVar' => 'mah'
// ... Other properties to set
);
Таким образом, класс циклически перебирает массив и использует ключ для вызова правильного метода для установки значения. Думаю, ничего сложного.
Более сложным является тестирование.
Поскольку это абстрактный класс, я не могу создать его экземпляр напрямую, но я должен его высмеивать.
Моя проблема в том, что я не могу передать конструктору правильные параметры, чтобы проверить правильность назначения значений.
Я пытался использовать что-то вроде:
public function testPerson()
{
$abstractClass = '\My\Namespace\Person';
$testData = array(
'id' => 1,
'createdOn' => '2015-01-07 19:52:00',
'unfound' => 'Inexistent method'
);
$methods = array(
'getId',
'setId'
);
$mock = $this->getMockBuilder($abstractClass)
->setConstructorArgs(array($testData))
->setMethods($methods)
->getMockForAbstractClass();
$this->assertEquals($testData['id'], $mock->getId());
}
В testPerson () переменная $ Methods не содержит всех необходимых мне методов, но для тестирования теста (пожалуйста, извините за игру со словами! :)) я думаю, что их достаточно.
Но PHPUnit говорит мне, что:
Failed asserting that null matches expected 1.
Кажется, что конструктор не вызывается, даже если покрытие кода говорит мне, что методы вызваны.
Есть ли кто-нибудь, кто может помочь мне понять, что происходит, и как я могу проверить этот класс?
Спасибо!
Решение очень простое: удаление $methods
переменная и призыв к setMethods($methods)
решил проблему!
призвание setMethods()
фактически «заглушает» те методы, которые, не устанавливая правильное фиксированное значение, устанавливаются в нуль (значение, которое я получил от результата испытаний).
Метод, который я тестировал, был ошеломлен, а остальные нет.
Так что print_r($mock)
показал, что другие значения были установлены правильно.
Так просто, но так трудно найти!
В любом случае, спасибо, что заставили меня задуматься, поэтому я решил проблему и задал вопрос!
Других решений пока нет …