CakePHP2系でComponentの単体テストを行って躓いた話

概要

CakePHP2系のアプリケーションに、新規でComponentを作成した。 そのComponentに対して、単体テストを行うとしたところ躓いたので残しておく。

内容

Componentに対して単体テストを作成し、公式ドキュメントを参考にsetUpに下記を記述。

public function setUp()
{
    parent::setUp();
    $CakeRequest      = new CakeRequest();
    $CakeResponse     = new CakeResponse();
    $this->Controller = new テスト用Controller($CakeRequest, $CakeResponse);
    $Collection       = new ComponentCollection();
    $this->Component = new テスト対象のComponent($Collection);
    $this->Component->startup($this->Controller);
}

これでテストケースを書いて実行したところ、テストケースが正常に走らなかった。 エラーログを確認したところ、下記が出力されている。

Error: Fatal Error (1): Call to a member function メソッド名() on a non-object

この出力されたメソッドはテスト用Controllerの親クラス(AppController)に定義されており、Webページとしてアクセスする分には問題なく利用できている。

何が原因なんだ…。

解決

テストケースのsetUp内に $Collection->setController($this->Controller); を追加することで解決した。

エラーログを見ると、メソッドがないと怒られているので テスト対象のComponent 内でControllerから受け取った値を見てみた(下記コードのgetController結果)。 すると、値がnullとなっており、Controllerがセットされていないことがわかった。

public function __construct(ComponentCollection $collection, $settings = array())
{
    $this->Controller = $collection->getController();
    parent::__construct($collection, $settings);
}

getがあるなら、setがあるだろうとCakePHPのコードを確認したところ、setControllerがあったのでビンゴ。 setControllerを呼び出すことで解決した。

public function setUp()
{
    parent::setUp();
    $CakeRequest      = new CakeRequest();
    $CakeResponse     = new CakeResponse();
    $this->Controller = new テスト用Controller($CakeRequest, $CakeResponse);
    $Collection       = new ComponentCollection();
    $Collection->setController($this->Controller);
    $this->Component = new テスト対象のComponent($Collection);
    $this->Component->startup($this->Controller);
}

以上、誰かのためになったら良いなと思い残しておきます。 最後まで読んで頂きありがとうございました。

参考

https://book.cakephp.org/2.0/ja/development/testing.html#id27