privateメソッドのテスト

今日のレガシー対応

privateメソッドをテストハーネスに入れた

あるクラスのprivateメソッドのテストをしたい
class Hoge {
	public pubMethod(){
		$this->meth1();
		・・・
		$this->meth2();
		・・・
	}
	private meth1(){
		・・・
	}
	private meth2(){
		・・・
	}
}
本当は設計を見直して別のクラスに切り出すべき
class Hoge {
	public pubMethod(){
		$fuga = new Fuga();

		$fuga->meth1();
		・・・
		$fuga->meth2();
		・・・
	}
}
class Fuga {
	public meth1(){
		・・・
	}
	public meth2(){
		・・・
	}
}

(pubMethodでFugaをnewしてるのがいいのかはまた別として・・・)

でも派手なリファクタリングはできないのでprivateをprotectedにした
class Hoge {
	public pubMethod(){
		$this->meth1();
		・・・
		$this->meth2();
		・・・
	}
	protected meth1(){
		・・・
	}
	protected meth2(){
		・・・
	}
}

↓テストコード

class HogeTest extends PHPUnit_Framework_TestCase {
	public function setUp(){
		$this->obj = new TestingHoge();
	}
	public function testMeth1(){
		・・・・
	}
	public function testMeth2(){
		・・・・
	}
}

class TestingHoge extends Hoge {
	public meth1(){
		return $this->meth1();
	}
	public meth2(){
		return $this->meth2();
	}
}

これってどうなの?

既存のコードに大幅に手を入れることができないので

しょうがなかったんや・・・

privateメソッドをprotectedにすることが(今回は)安全だった

↓のような理由でアクセスレベルがゆるくなる分には問題なしと判断できた。
このクラスを継承したりする場合にはなんかあるかもしれないけど、このプロジェクトではクラスの継承は特定のケースに限られている。

残る疑問

ほかのクラスのメソッドを呼び出してるメソッドのテスト

先の例で言うと「Hoge::pubMethod()」。
このメソッドのテストってどうするべきなのか・・・

  • 普通にこのままテスト
    • Fugaクラスのメソッドのテストを2重に行うことになるのでは?
  • Fugaクラスのモックを用意してテストすべき
    • ややこしくなってまいりました
  • Hoge::pubMethod()自体がやってることがほとんどないなら無理にテストしなくても
    • それもどうかと
参考にできる実例がなかなかない

いやレガシーコード改善ガイド嫁といわれればそれまでですが、時間や権限や状況によってとりうる手段が限られてきたりすると思うので・・・
ほんとにゆるーい感じの個人的な実例なども見てみたいです。