Имитация вашего объекта:
class Relay
{
private $privateProperty;
public function __construct()
{
$this->privateProperty = new \stdClass();
}
// метод, который работает с приватным свойством
public function call()
{
return $this->privateProperty;
}
}
Способ 1: Нативный PhpUnit + Reflection API
use PHPUnit\Framework\TestCase;
class RelayTest extends TestCase
{
public function testCall(): void
{
$reflectionClass = new \ReflectionClass(Relay::class);
$reflectionProperty = $reflectionClass->getProperty('privateProperty');
$reflectionProperty->setAccessible(true);
// создаем наш объект БЕЗ конструктора
$relay = $reflectionClass->newInstanceWithoutConstructor();
// Меняем свойство и вызываем метод, работающий с этим приватным полем
$reflectionProperty->setValue($relay, 1111);
self::assertEquals(1111, $relay->call());
// Меняем свойство и вызываем метод, работающий с этим приватным полем
$reflectionProperty->setValue($relay, 'aaaa');
self::assertEquals('aaaa', $relay->call());
}
}
Способ 2: Через Codeception Stub
class RelayTest extends TestCase
public function testCall(): void
{
/** @var Example $stub */
$stub = Stub::make(Relay::class, [
'privateProperty' => 1111,
]);
self::assertEquals(1111, $stub->call());
$stub = Stub::make(Relay::class, [
'privateProperty' => 'aaaa',
]);
self::assertEquals('aaaa', $stub->call());
}
}
Отступления и полезные советы:
- Почему-то стандартный, давно используемый мною, способ с инъекцией в мок приватного филда не зашел и выдавал null всегда.
- Юзайте Inversion of Control Principle, например инъекцию зависимости через конструктор или инъекцию через метод с присвоением в конструкторе NullObject. Оба способа будут хороши для тестирования.