

前回質問させていただいた以下の回答で、別の疑問点が出てきたので質問します。  
[PHPUnitのモック機能を使いテストを行いたいのですが、うまく置き換わってくれません。](https://ja.stackoverflow.com/questions/30270/)

前回の質問では、メソッドがとあるメソッドに依存しており、

[code]

    class Item_Relation extends \Utility\base {
        public function get_item_master_id($account, $item_name) {
            $item_master_instance = new \Utility\Item_Master();
            $item_master_id = $item_master_instance->get_id($account, $item_name);
            return $item_master_id;
        }
    }
    
[/code]

テストコードを書くためにアスペクト指向の書き方ができる  
モックライブラリ（ここではAspectMock）を導入する必要があることがわかりました。

[code]

    use \AspectMock\Test as test;
    class Test_Item_Relation extends TestCase {
        /**
         * @test
         */
        public function get_item_master_id_サンプルテスト() {
            /* テストダブルの作成 */
            test::double('\Utility\Item_Master', [get_id => '戻り値'])
    
            /* 呼び出し */
            $item_relation_instance = new \Utility\Item_Relation();
            $item_master_id = $item_relation_instance->get_master_id($account, $item_name);
    
            /* 比較 */
            $this->asserSame('戻り値', $item_master_id);
    
            /* テストダブルの削除 */
            test::clean();
        }
    }
    
[/code]

回答のコメントで、依存性があるインスタンスを注入することができれば、  
PHPUnitで用意されているメソッドでテストが書けると指摘がありましたが

[code]

    /* 元のコード */
    class Item_Relation extends \Utility\base {
        /**
         * @param string               $account
         * @param \Utility\Item_Master $item_master_instance
         * @return int
         */
        public function get_item_master_id($account, $item_master_instance) {
            $item_master_id = $item_master_instance->get_id($account, $item_name);
            return $item_master_id;
        }
    }
    
    /* テストコード */
    class Test_Item_Relation extends TestCase {
        /**
         * @test
         */
        public function get_item_master_id_サンプルテスト() {
            /* モックの作成 */
            $item_master_mock = $this->getMockBuilder(\Utility\Item_Master::class)
                ->setMethods(['get_id'])
                ->getMock();
            $item_master_mock->expects($this->once())
                ->method('get_id')
                ->will($this->returnValue('戻り値'));
    
            /* 呼び出し */
            $item_relation_instance = new \Utility\Item_Relation();
            $item_master_id = $item_relation_instance->get_item_master_id($account, $item_master_mock);
    
            /* 比較 */
            $this->asserSame('戻り値', $item_master_id);
        }
    }
    
[/code]

一番上の呼び出し元（ここではMVCにおけるコントローラー）では  
必ず依存性のある書き方が必要になると考えています。

[code]

    class Sample extends Controller {
        public function action_index() {
            /* 初期処理 */
            ～～～～
            /* 依存関係がコントローラーで発生してしまう */
            $item_relation_instance = new \Utility\Item_Relation();
            $item_relation_instance->get_item_master_id(/* 引数 */);
            ～～～～
            /* 後処理 */
        }
    }
    
[/code]

ここで2点質問なのですが、

  * 依存性のない書き方は可能なのか？（依存性を排除した書き方ができればPHPUnitの標準機能だけでテストすることが可能なので）
  * 依存性のあるメソッド（コントローラー）のテストの自動化のより良い方法  
について教えていただけると幸いです。


CC BY-SA 4.0
2016-11-18T02:38:03.930
30491
2019-06-03T03:31:19.900
2019-06-03T03:31:19.900
32986
7918
question
php テスト
コントローラーのテストコードの書き方、依存性の無いコードの書き方について