リフレクションってなんでしょうか。
情報工学においてリフレクション (reflection) とは、プログラムの実行過程でプログラム自身の構造を読み取ったり書き換えたりする技術のことである。
(wikipediaより引用)
つまりは「クラスの構造をあれこれできる便利なもの」ということらしいです。
いろいろな使い道がありそうですね。今回はリフレクションクラスを使ってユニットテストでprivateメソッド、private変数を検証する例を紹介します。
PHPマニュアル リフレクション
http://www.php.net/manual/ja/book.reflection.php
privateメソッドを外部から呼び出す
class Foo { private function func1($text) { return $text; }
リフレクションクラスを使ってprivateメソッドのfunc1を検証してみましょう。
function callFoo() { $foo = new foo(); $method = new ReflectionMethod(get_class($foo), 'func1'); $method->setAccessible(true); $this->assertEquals('demo text', $method->invoke($foo, 'demo text')); }
ポイントはsetAccessible(true)の部分です。
trueを渡すとprivateやprotectedなメソッドがアクセス可能になります。
private変数を外部から変更する
class Foo { private $num = 1; public function func2() { return $this->num * 100; } }
次はprivate変数のnumの値を変更してみます。
function callFoo2() { $foo = new foo(); $reflectionClass = new ReflectionClass(get_class($foo)); $property = $reflectionClass->getProperty('num'); $property->setAccessible(true); $property->setValue($foo, 5); $this->assertEquals(500, $foo->func2()); }
さっきprivateメソッドを呼び出した時と同じようにsetAccessible(true)を呼び出すことで、setValue()で値を上書きすることができます。
変数の値が知りたい時はgetValue()を使用します。
まとめ
プライベートメソッドのユニットテストについては、すべきかどうか議論が分かれています。パブリック経由でのテストが行えず、テスト用コードを書き加えたくない場合にはリフレクションクラスを使うのもひとつの手段になると思います。
クラスやメソッドがstaticの場合は呼び出し方法が異なるのでマニュアルを参照してください。