CakePHPでModelのテストが失敗する時の対応(解決)

2014-01-12
PHP
CakePHP

以前のエントリで「CakePHPでModelのテストが失敗する時の対応」というのを書いたが、 ついにスッキリと解決することが出来た!  

原因

結局のところ、原因はクラスのオートローダーにあった。 CakePHPの仕組みでは、クラスのオートローダーとして App::load()関数が使われている。

ところが・・・ Composer経由でinstallしたPHPUnitを利用してテストを行う場合、PHPUnit自体の読み込みとしてComposerのautoloaderを利用するので、 phpunitのtest実行時は、オートローダーが2種類存在することになる。

1つ目 => Composerのオートローダー ※test実行の為、PHPUnitが先に読み込まれている必要がある。
2つ目 => CakePHPのオートローダー  

そして、Composer側のオートローダーには、なんとbakeしたModel名のロード設定が書かれている、こんな感じに!

1
'MyUser' => $vendorDir . '/pear-pear.cakephp.org/CakePHP/Cake/Test/Case/Model/models.php'

上の例でいくと、MyUserというmodelのテストを実行すると、クラスのオートローダーが実際にテストしたいmodelを読み込む前に CakePHPのcore側のディレクトリにあるテスト用のMockモデルを読みにいってしまう。

こうなるとお手上げで、自分の作ったModelは絶対に読み込まれないので、前エントリでやったようにオートローダーが動くより前に 絶対パスでincludeするしか、手がなくなってしまう。

※ちなみにオートローダーの使用する関数をチェックするには、spl_autoload_functions関数を使えば一発。これトテモトテモ大事。

解決法

core側のディレクトリにあるモックモデルの定義ファイルから、テストしたいModel名のモッククラス定義を削除します。

1
$ vi Vendor/pear-pear.cakephp.org/CakePHP/Cake/Test/Case/Model/models.php'

こんな記述があるから、マルっと削除 bake時に同時にtestも作るとここに追加される模様。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/**
* MyUser class
*
* @package Cake.Test.Case.Model
*/
class MyUser extends CakeTestModel {

/**
* name property
*
* @var string
*/
public $name = 'MyUser';
}

そんでもって、composerのautoloaderを、以下のコマンドで再作成します。

1
php composer.phar dump-autoload

これにて、App::usesの記述だけで、自分の作成したModelが読み込めるようになりました。 ( ´ー`)フゥー...大分手間取ってしまった。

教訓

(1)クラスが読み込まれない場合は、オートローダーでの読み込みがうまくいってないという勘が働くようにすること!
(2)オートローダーで使われる関数は、spl_autoload_functions()関数で確認できる。ワスレナイこと。( ゚д゚ )クワッ!!