今回はLaravelでprivateなメソッドのテスト方法を調べてみたことのメモです。
環境
- PHP 7
- PHPUnit 5.6
- Laravel 5.3
PHPでprivateなメソッドのテスト方法
PHPでprivateなテストを行う方法は以下の2つがあります。
-
- Reflection
-
- Closure
この記事ではClosure
を押します。
Reflection
Reflection(リフレクション)
とは、簡単に言うと[自分自身の構造を読み取って操作する]ものと言えば良いでしょうか。
コードはこんな感じです。
1$who = new Who();
2
3$method = new ReflectionMethod($who, 'privateMethod');
4$method->setAccessible(true);
5$method->invoke();
「やったわー、こんなのJavaでいっつもやってたわー。」と言うコードですね。
privateメソッドを読み取ってアクセス権を付与し、実行しているわけですが、リフレクションのこういった処理に回りくどさを感じます。
Clousure
PHP5.3に実装された無名関数は、PHP5.4でパワーアップし、 生成した無名関数をコントロール できるようになっています。
Closure::bind()
でクラスをバインドすると、クロージャ内でprivateにアクセスできる、、、つまり_プライベート領域を好きなように操作_することができやりたい放題なんですね!
Clousureを使ったテストはこのように実装することができます。
private functionのテスト
1public function testWhoPrivate()
2{
3 Closure::bind(function() {
4
5 $who = new WhoService();
6 $this->assertTrue( $who->privateMethod() );
7
8 }, $this, WhoService::class)->__invoke();
9}
Closureの中でassertまでできますから、これだけでOKです。 覚えることが少なくていいですね!
同様に、privatなメンバを書き換えてテストすることもできます。
1public function testWho()
2{
3 Closure::bind(function() {
4
5 $who = new WhoService();
6 $who->privateVar = 8;
7
8 }, $this, WhoService::class)->__invoke();
9}
何か値を渡したいときは普通にuseを使えばOKです。
1public function testWho()
2{
3 $testValue = 8;
4 Closure::bind(function() use(testValue) {
5
6 $who = new WhoService();
7 $who->privateVar = testValue;
8
9 }, $this, WhoService::class)->__invoke();
10}
private static funciton
staticなテストの方法は、対象メソッドをstaticで呼び出すだけです。
1public function testWho()
2{
3 Closure::bind(function() {
4
5 $this->assertTrue( WhoService::privateStaticMethod() );
6
7 }, $this, WhoService::class)->__invoke();
8}
どちらが良いか
[PHPUnit private テスト]でググると、比較的にリフレクションの情報が出てくるように感じますが、クロージャでテストを組み立てたほうが記述がシンプルになって使いやすいと思います。 私はクロージャがおすすめです。
新しいバージョンのLaravelプロジェクトであれば、どちらも対応バージョンですから、どうぞ好きなようにしてください。
おわりに
でっかいテストを書こうとすると消耗してしまい、テストが苦痛になります。
それではいけません。
プライベートメソッドが簡単にテストできれば、、、
- 粒度の細かいテストをたくさん書くことができ
- カバレッジがグングン上がり
- テストの成果を感じられ
- テストが楽しくなる
といういい流れになりますよ!
Every One Happy! すわー。
参考
PHP5.4時代のprivateメソッドテスト手法 #php5_4
http://blog.tojiru.net/article/239067872.html