LoginSignup
6
5

More than 3 years have passed since last update.

Cakephp3で Unitテストをするときの RecordNotFoundException例外との付き合い方

Last updated at Posted at 2016-06-03

概要

Cakephp3で edit アクションを作るとき、存在しないデータを editしようとすると
RecordNotFoundException 例外が発生します。
例えば、http://....../controller/edit/99999999 にアクセスすると、Cakeのエラー画面になります。
Unitテストのログも下記のようなものが出てきます。

1) App\Test\TestCase\Controller\SomeControllerTest::testEdit
Cake\Datasource\Exception\RecordNotFoundException: Record not found in table "something" in /var/www/app/vendor/cakephp/cakephp/src/Datasource/QueryTrait.php:410
Stack trace:
#0 /var/www/app/vendor/cakephp/cakephp/src/ORM/Table.php(1201): Cake\ORM\Query->firstOrFail()
#1 /var/www/app/src/Controller/SomeController.php(86): Cake\ORM\Table->get(Array, Array)
#2 [internal function]: App\Controller\SomeController->edit('10000')

例外を抑制するにはどうしたらよいか、
例外が出る場合のUnitテストはどうするのか
例外でUnitテストが途中で止まるのをなんとかしたい、
ということでまだスッキリ解決していないものの現状を書いてみました。

問題点

・例外の出方がイマイチ不明で、テストの時の挙動も不明。
例えば、

  • Controllerの中でTry-catch で例外を捕捉できるが
app/src/Controller/SomeController.php
$this->SomeTable->get($id, [
            'contain' => []
        ]);
  • Table の中では例外が捕捉できない。
app/src/Model/Table/SomeTable.php
$this->get($id, [
            'contain' => []
        ]);

Tableの中で例外が捕捉できないなら、getメソッドを自作すればよいかも、と思ったものの try-catch はapp/vendor/cakephp/cakephp/src/ORM/Table.php にあるgetの中には存在せず、
app/vendor/cakephp/cakephp/src/ORM/Behavior/TreeBehavior.php の中でthrowしていたり、
app/vendor/cakephp/cakephp/src/Datasource/QueryTrait.php の中でthrowしていたり、
かなり深い部分を探る必要がありそうです。

つまりTableの中で例外を捕捉せず、コントローラ側で RecordNotFoundException例外などをTry-catchすべきなのでしょう。

テストでの挙動

Controller のテスト

アサーションの結果と違う場合には例外が出てテストが途中で終了し、
アサーション通りだとテストが成功するようです。

app/tests/TestCase/Controller/SomeControllerTest.php
// 下記のように書くと例外は確認出来ず
$this->assertResponseError();

// 下記のように書くと例外が発生する。
$this->assertResponseOk();
app/tests/TestCase/Controller/SomeControllerTest.php
//この例外が発生しているところで
$this->expectException('Cake\Datasource\Exception\RecordNotFoundException');
$this->assertResponseOk();

// あるいはアノテーションで
/**
* @expectedException \Cake\Datasource\Exception\RecordNotFoundException
*/
public function someEditTest(){
    ..........................
    $this->assertResponseOk();

というようにテスト関数の前に書いても例外は発生してテストが中断します。

Tableのテスト

例外は、expectException で宣言しておくとテストが止まらないものの、
例外が発生した箇所より後は何も実行されません。

app/tests/TestCase/Model/Table/SomeTableTest.php
$this->expectException('Cake\Datasource\Exception\RecordNotFoundException');
debug('このデバッグ文は表示されますが');
$this->SomeTables->dosomething($data);
debug('このデバッグ文は表示されません');
//このAssertionも実行されません。
$this->assertFalse($result);

結論

  • 例外をTry-catch するなら、Controllerでやると良さそう。
  • テストでは、Controllerのテストで例外が出ないようにし、
  • Tableのテストでは例外が出ることを確認できる。
6
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
5