Controllerのテスト例を書きます。
bin/cake bake test Controller ArticlesController
とかのbakeでファイルが生成される(Controllerのbakeでも一緒にできているはず)ので、それをベースに編集したらいいと思います。
メソッド名は『test』で始まっていれば何でも大丈夫です。(わかりやすい名前がいいと思うけど)
参考:
Cookbook 3.x テスト
PHPUnit 用のテストの書き方 - アサーション
表示できるかのテスト
まずは表示できないと始まりません。
public function testIndex()
{
$this->get('/articles');
$this->assertResponseOk();
$this->assertResponseContains('>ログイン</a>');
$this->assertCount(10, $this->viewVariable('articles'));
}
/articlesへのGETリクエストで2xxのレスポンスが返ってくることをテストしています。
get()
以外に、post()
、put()
、delete()
、patch()
もできます。
assertResponseContains()
で、レスポンス内容に『>ログイン</a>
』が含まれていることなどもテストできます。
$this->viewVariable()
によりControllerでset()
した値が取れるので、正しく値がセットされているか等がテストできます。
表示がエラーになることのテスト
無効なパラメータや不正なアクセスの時に例外を投げる処理がある場合、それをテストします。
public function testViewInvalid()
{
$this->get('/articles/view/hoge');
$this->assertResponseError();
// または以下でも可
$this->setExpectedException('Cake\Network\Exception\NotFoundException');
$this->get('/articles/view/hoge');
}
4xx(NotFound等)のレスポンスをテストする$this->assertResponseError()
でエラーになることをテストします。
また、期待する例外(というのも変だけど)をsetExpectedException()
で指定してget()
などの前に書けば、特定のExceptionが発生していることをテストすることができます。
データを登録するテスト
フォームに何かを入力してDBに保存できることをテストします。
public $fixtures = [
'app.articles',
]
private $__initialCount = null;
public function setUp()
{
parent::setUp();
$this->articles = TableRegistry::get('Articles');
$this->__initialCount = $this->articles->find()->count();
}
public function tearDown()
{
parent::tearDown();
unset($this->articles);
$this->__initialCount = null;
}
public function testAddPost()
{
$data = [
'title' => 'TEST title',
'start_date' => [
'year' => '2016',
'month' => '03',
'day' => '24',
]
];
$this->post('/articles/add', $data);
$this->assertRedirect(['action' => 'index']);
$this->assertEquals($this->__initialCount + 1, $this->articles->find()->count());
}
$data
の内容をPOSTし、indexにリダイレクトされることをassertRedirect()
でテストします。
またDBのレコードが1つ増えていることをテストします。
バリデーションエラーになることのテスト
同様に、データをPOSTした時にバリデーションに引っかかってDBに保存できないことをテストします。
public function testAddPostError()
{
$data = [
'title' => ''
];
$this->post('/articles/add', $data);
$this->assertNoRedirect();
$this->assertNotEmpty($this->viewVariable('article')->errors());
$this->assertArrayHasKey('title', $this->viewVariable('article')->errors());
$this->assertEquals($this->__initialCount, $this->articles->find()->count());
}
$this->viewVariable()
でテンプレートにアサインされた(Controllerで$this->set()
された)変数が取れるので、バリデーションエラーがある場合にセットされているerrors()
が空じゃないこと、titleにエラーがあること等をテストします。
リダイレクトがなく、DBにもレコードが増えていないことをテストします。
ログインが必要なページのテスト
ログイン認証が必要なページは、セッションにログインしていることにしたい人の情報を入れることでログイン済みとしてアクセスさせることができます。
public function testMypage()
{
$this->session(['Auth' => [
'User' => [
'id' => 1,
'email' => 'test1@example.com',
'name' => '山田太郎',
...
]
]]);
$this->get('/mypage');
$this->assertResponseOk();
$this->assertResponseContains('山田太郎さんこんにちは');
}
Cookieも$this->cookie('name', 'value')
でセットすることができます。
送信するリクエストを設定してテスト
headerや$this->request->env()
で取得できるような値も$this->configRequest()
で設定することができます。
$this->request->clientIp()
を見てアクセス制限をしているようなアプリケーションもテストすることができます。
public function testIpAccess()
{
$this->configRequest([
'headers' => ['CLIENT_IP' => '12.34.56.78'],
'environment' => ['REMOTE_ADDR' => '23.45.67.89']
]);
$this->get('/limitedpage');
$this->assertResponseOk();
}
headers
に指定した値は、頭に『HTTP_』が付く値(上記例ならHTTP_CLIENT_IP)として設定されます。(Controller内の$this->request->env('HTTP_CLIENT_IP')で'12.34.56.78'が返るようになります。)