ググれば出てくるので今更感は否めないのですが、Reflection を利用して実現するのが一般的ですね。ただ、TestCaseの記述には時間をかけたくないものです。
exampleClass.php
<?php
class Example
{
private function sampleMethod()
{
return true;
}
}
exampleClassTest.php
class function ExampleTest
{
protected $object;
protected function setUp()
{
$this->object = new Example;
}
public function sampleMethodTest()
{
$reflection = new \ReflectionClass($this->object);
$method = $reflection->getMethod('sampleMethod');
$method->setAccessible(true);
$res = $method->invoke($this->object);
$this->assertTrue($res);
}
}
まあ、こんな具合…。
ずぼらなんで、この5行が面倒くさい。
そこで、こんなことしてみました。
trait.php
<?php
trait CommonTrait
{
public function __call($name, $arguments = array())
{
if (MODE === TEST) {
$reflection = new \ReflectionClass($this);
$method = $reflection->getMethod($name);
$method->setAccessible(true);
return $method->invokeArgs($this, $arguments);
} else {
$msg = 'アクセス不能なメソッドをコールしました。';
throw new Exception($msg);
}
}
public static function __callStatic($name, $arguments = array())
{
if (MODE === TEST) {
return $this->__call($name, $arguments);
} else {
$msg = 'アクセス不能なメソッドをコールしました。';
throw new Exception($msg);
}
}
exampleClass.php
<?php
class Example
{
use CommonTrait;
private function sampleMethod()
{
return true;
}
}
exampleClassTest.php
<?php
class function ExampleTest
{
protected $object;
protected function setUp()
{
$this->object = new Example;
}
public function sampleMethodTest()
{
$res = $this->object->sampleMethod();
$this->assertTrue($res);
}
}
定数のMODE, TESTは実行環境がテスト環境であることを表しています。
そうでないと、いつでもprivate, protected な method が実行できてしまうので…。
実行モードはbootstrap.php に定義しておくだけですね。
bootstrap.php
<?php
ini_set('include_path'
, ini_get('include_path')
. PATH_SEPARATOR . '/usr/share/pear'
);
// テスト環境
if (!defined('TEST')) {
define('TEST', 1);
}
// 開発環境
if (!defined('DEVELOPPING')) {
define('DEVELOPPING', 2);
}
// 本番環境
if (!defined('PRODUCTION')) {
define('PRODUCTION', 3);
}
// 実行モード
define('MODE', TEST);