Подмена защищенных и приватных свойств для тестирования

Подмена защищенных и приватных свойств для тестирования

Иногда в тестах нам необходимо прочитать/заменить protected или private свойство объекта.

Когда данный трюк может пригодится?

Если вам понадобился данный трюк то скорее всего вы имеете проблему в архитектуре класса/приложения. Его использование данное крайняя мера. Лучше всего тестировать приватные свойства и способы через публичные способы. Использование данного трюка оправдано в случае экономии времени и только, как временное решение.

Пример тестируемого класса:

class Suit {private $private_property = 'private property value';}

Чтение защищенных и приватных свойств

Чтобы прочитать свойство $private_property на иное нам поможет ReflectionProperty. Создаем способ read_inaccessible_property:

private function read_inaccessible_property( $object, string $property_name) {$property = new ReflectionProperty( $object, $property_name);$property->setAccessible( true);$value = $property->getValue( $object);$property->setAccessible( false);return $value;}

Разберем работу способа построчно:

  • При помощи ReflectionProperty получаем в виде объекта свойство private_property объекта класса Suit;
  • Делаем свойство доступным для редактирования;
  • Читаем свойство private_property объекта класса Suit;
  • Делаем свойство недоступным для редактирования;
  • И возвращаем результат.

Пример теста в полном объеме:

use PHPUnit\Framework\TestCase;use ReflectionProperty;class Test_Suit extends \PHPUnit\Framework\TestCase {private function read_inaccessible_property( $object, string $property_name) {$property = new ReflectionProperty( $object, $property_name);$property->setAccessible( true);$value = $property->getValue( $object);$property->setAccessible( false);return $value;}public function test_read_property() {$suit = new Suit();$property = $this->read_inaccessible_property( $suit, 'private_property');$this->assertSame( 'private property value', $property);}}

Обновление защищенных и приватных свойств

Для замены защищенного/приватного свойства нам понадобится все тот же ReflectionProperty. Создадим способ update_inaccessible_property:

private function update_inaccessible_property( $object, string $property_name, $value) {$property = new ReflectionProperty( $object, $property_name);$property->setAccessible( true);$property->setValue( $object, $value);$property->setAccessible( false);}

Разберем построчно:

  • При помощи ReflectionProperty получаем в виде объекта свойство private_property объекта класса Suit;
  • Делаем свойство доступным для редактирования;
  • Устанавливаем для свойства private_property объекта класса Suit новое значение;
  • Делаем свойство недоступным для редактирования;

Пример теста в полном объеме:

use PHPUnit\Framework\TestCase;use ReflectionProperty;class Test_Suit extends \PHPUnit\Framework\TestCase {private function read_inaccessible_property( $object, string $property_name) {$property = new ReflectionProperty( $object, $property_name);$property->setAccessible( true);$value = $property->getValue( $object);$property->setAccessible( false);return $value;}private function update_inaccessible_property( $object, string $property_name, $value ) {$property = new ReflectionProperty( $object, $property_name );$property->setAccessible( true );$property->setValue( $object, $value );$property->setAccessible( false );}public function test_update_private_property() {$suit = new Suit();$this->update_inaccessible_property( $suit, 'private_property', 'new private property value' );$property = $this->read_inaccessible_property( $suit, 'private_property' );$this->assertSame( 'new private property value', $property );}}

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *