60
63

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

CakePHP3でControllerのユニットテストを書く例

Posted at

Controllerのテスト例を書きます。
bin/cake bake test Controller ArticlesControllerとかのbakeでファイルが生成される(Controllerのbakeでも一緒にできているはず)ので、それをベースに編集したらいいと思います。
メソッド名は『test』で始まっていれば何でも大丈夫です。(わかりやすい名前がいいと思うけど)

参考:
Cookbook 3.x テスト
PHPUnit 用のテストの書き方 - アサーション

表示できるかのテスト

まずは表示できないと始まりません。

tests/TestCase/Controller/ArticlesControllerTest.php
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()した値が取れるので、正しく値がセットされているか等がテストできます。

表示がエラーになることのテスト

無効なパラメータや不正なアクセスの時に例外を投げる処理がある場合、それをテストします。

tests/TestCase/Controller/ArticlesControllerTest.php
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に保存できることをテストします。

tests/TestCase/Controller/ArticlesControllerTest.php
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に保存できないことをテストします。

tests/TestCase/Controller/ArticlesControllerTest.php
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にもレコードが増えていないことをテストします。

ログインが必要なページのテスト

ログイン認証が必要なページは、セッションにログインしていることにしたい人の情報を入れることでログイン済みとしてアクセスさせることができます。

tests/TestCase/Controller/ArticlesControllerTest.php
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()を見てアクセス制限をしているようなアプリケーションもテストすることができます。

tests/TestCase/Controller/ArticlesControllerTest.php
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'が返るようになります。)

60
63
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
60
63

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?