Edited at

PHPでprivateメソッドをテストしやすくする

More than 3 years have passed since last update.

class foo {

private function bar($a){
return $a . 'bar';
}
}

こんなクラスがあってprivateメソッドをテストする方法をぐぐるとReflectionMethodをつかって下記みたいに書くって情報がいっぱいひっかかります。

$foo = new foo();

$method = new ReflectionMethod($foo, 'bar');
$method->setAccessible(true);

$result = $method->invoke($foo, 'StringA');
$this->assertEqual($result, 'StringAbar');

慣れればすぐに何やってるかわかるようになるんでしょうけど、正直いって長くてパッと見よくわかんない。

で、めんどくさがりの私は下記みたいなテスト用クラスつくってみた。

class fooTesting extends foo{

public function __call($methodName, $params)
{
if(substr($methodName,0, 9) == '_testing_'){
$callName = substr($methodName, 9);
$method = new ReflectionMethod($this, $callName);
$method->setAccessible(true);
$result = $method->invokeArgs($this, $params);
return $result;
}else{
return parent::__call($methodName, $params);
}
}
}

これ使ってテストする方法は呼び出したいプライベートメソッドに_testing_を頭につけて呼び出すだけ。

$foo = new fooTesting();

$result = $foo->_testing_bar('StringA');
$this->assertEqual($result, 'StringAbar');

CakePHPのModelのテストで使うときはTestingクラスにAliasで元クラスの名前指定してClassRegistory::init()してあげれば元クラスと同じように使えるはずです。


追記

2015/06/18 ラッパークラス作ってみました。→自動テスト - PHPでprivateメソッドをテストしやすくするTestingWrapper - Qiita