コントローラーのテスト

いくつかの新しいヘルパークラスとトレイトを使用することで、コントローラーのテストが容易になります。コントローラーのテストでは、アプリケーション全体のブートストラッププロセスを実行することなく、コントローラー内のコードを実行できます。フィーチャートールを使用する方が簡単な場合が多いですが、必要な場合はこの機能を使用できます。

注記

フレームワーク全体がブートストラップされていないため、この方法でコントローラーをテストできない場合があります。

ヘルパートレイト

コントローラーテストを有効にするには、テスト内でControllerTestTraitトレイトを使用する必要があります。

<?php

namespace CodeIgniter;

use CodeIgniter\Test\CIUnitTestCase;
use CodeIgniter\Test\ControllerTestTrait;
use CodeIgniter\Test\DatabaseTestTrait;

class TestControllerA extends CIUnitTestCase
{
    use ControllerTestTrait;
    use DatabaseTestTrait;
}

トレイトを含めたら、リクエストとレスポンスクラス、リクエストボディ、URIなどを含む環境の設定を開始できます。controller()メソッドを使用して使用するコントローラーを指定し、コントローラーの完全修飾クラス名をパラメーターとして渡します。最後に、実行するメソッドの名前をパラメーターとしてexecute()メソッドを呼び出します。

<?php

namespace CodeIgniter;

use CodeIgniter\Test\CIUnitTestCase;
use CodeIgniter\Test\ControllerTestTrait;
use CodeIgniter\Test\DatabaseTestTrait;

class TestControllerA extends CIUnitTestCase
{
    use ControllerTestTrait;
    use DatabaseTestTrait;

    public function testShowCategories()
    {
        $result = $this->withURI('http://example.com/categories')
            ->controller(\App\Controllers\ForumController::class)
            ->execute('showCategories');

        $this->assertTrue($result->isOK());
    }
}

ヘルパーメソッド

controller($class)

テストするコントローラーのクラス名を指定します。最初のパラメーターは、完全修飾クラス名(つまり、名前空間を含む)である必要があります。

<?php

$this->controller(\App\Controllers\ForumController::class);

execute(string $method, …$params)

コントローラー内で指定されたメソッドを実行します。最初のパラメーターは実行するメソッドの名前です。

<?php

$results = $this->controller(\App\Controllers\ForumController::class)
    ->execute('showCategories');

2番目以降のパラメーターを指定することで、コントローラーメソッドに渡すことができます。

これは、レスポンス自体を確認するための多くのルーチンを提供する新しいヘルパークラスを返します。詳細は下記を参照してください。

withConfig($config)

変更されたバージョンの **app/Config/App.php** を渡して、異なる設定でテストすることができます。

<?php

$config              = new \Config\App();
$config->appTimezone = 'America/Chicago';

$results = $this->withConfig($config)
    ->controller(\App\Controllers\ForumController::class)
    ->execute('showCategories');

指定しない場合、アプリケーションのApp設定ファイルが使用されます。

withRequest($request)

テストのニーズに合わせて調整された **IncomingRequest** インスタンスを提供できます。

<?php

$request = new \CodeIgniter\HTTP\IncomingRequest(
    new \Config\App(),
    new \CodeIgniter\HTTP\URI('http://example.com'),
    null,
    new \CodeIgniter\HTTP\UserAgent()
);

$request->setLocale($locale);

$results = $this->withRequest($request)
    ->controller(\App\Controllers\ForumController::class)
    ->execute('showCategories');

指定しない場合、デフォルトのアプリケーション値を持つ新しいIncomingRequestインスタンスがコントローラーに渡されます。

withResponse($response)

**Response** インスタンスを提供できます。

<?php

$response = new \CodeIgniter\HTTP\Response(new \Config\App());

$results = $this->withResponse($response)
    ->controller(\App\Controllers\ForumController::class)
    ->execute('showCategories');

指定しない場合、デフォルトのアプリケーション値を持つ新しいResponseインスタンスがコントローラーに渡されます。

withLogger($logger)

**Logger** インスタンスを提供できます。

<?php

$logger = new \CodeIgniter\Log\Handlers\FileHandler();

$results = $this->withResponse($response)
    ->withLogger($logger)
    ->controller(\App\Controllers\ForumController::class)
    ->execute('showCategories');

指定しない場合、デフォルトの設定値を持つ新しいLoggerインスタンスがコントローラーに渡されます。

withURI(string $uri)

このコントローラーが実行されたときにクライアントがアクセスしていたURLをシミュレートする新しいURIを提供できます。これは、コントローラー内でURIセグメントを確認する必要がある場合に役立ちます。パラメーターは有効なURIを表す文字列のみです。

<?php

$results = $this->withURI('http://example.com/forums/categories')
    ->controller(\App\Controllers\ForumController::class)
    ->execute('showCategories');

予期せぬ事態を避けるために、テスト中に常にURIを提供することをお勧めします。

注記

v4.4.0以降、このメソッドはURIを持つ新しいRequestインスタンスを作成します。RequestインスタンスはURIインスタンスを持つ必要があります。Config\AppでURI文字列のホスト名が無効な場合、有効なホスト名が設定されます。

withBody($body)

リクエストにカスタムボディを提供できます。これは、JSON値をボディとして設定する必要があるAPIコントローラーをテストする場合に役立ちます。パラメーターはリクエストのボディを表す文字列のみです。

<?php

$body = json_encode(['foo' => 'bar']);

$results = $this->withBody($body)
    ->controller(\App\Controllers\ForumController::class)
    ->execute('showCategories');

レスポンスの確認

ControllerTestTrait::execute()TestResponseのインスタンスを返します。レスポンステストで、このクラスを使用してテストケースで追加のアサーションと検証を実行する方法について説明します。

フィルターテスト

コントローラーテストと同様に、フレームワークはカスタムフィルターとプロジェクトでのルーティングでの使用をテストするのに役立つツールを提供します。

ヘルパートレイト

コントローラーテスターと同様に、これらの機能を有効にするには、テストケースにFilterTestTraitを含める必要があります。

<?php

namespace CodeIgniter;

use CodeIgniter\Test\CIUnitTestCase;
use CodeIgniter\Test\FilterTestTrait;

class FilterTestCase extends CIUnitTestCase
{
    use FilterTestTrait;
}

設定

コントローラーテストとの論理的な重複のため、FilterTestTraitControllerTestTraitと連携して動作するように設計されています。両方を同じクラスで使用する必要がある場合、トレイトを含めるとCIUnitTestCaseはそのsetUpメソッドを検出し、テストに必要なすべてのコンポーネントを準備します。特別な設定が必要な場合は、サポートメソッドを呼び出す前にプロパティを変更できます。

  • $request デフォルトのIncomingRequestサービスの用意されたバージョン

  • $response デフォルトのResponseInterfaceサービスの用意されたバージョン

  • $filtersConfig デフォルトのConfig\Filters設定(注:検出はFiltersによって処理されるため、モジュールエイリアスは含まれません)

  • $filters 上記の3つのコンポーネントを使用したCodeIgniter\Filters\Filtersのインスタンス

  • $collection Config\Routesの検出を含む、準備済みのRouteCollectionのバージョン

デフォルト設定は通常、本番プロジェクトを最も忠実にエミュレートするため、テストには最適ですが(例として)、フィルターがフィルターされていないルートで誤ってトリガーされる状況をシミュレートする場合は、設定に追加できます。

<?php

namespace CodeIgniter;

use CodeIgniter\Test\CIUnitTestCase;
use CodeIgniter\Test\FilterTestTrait;

final class FilterTestCase extends CIUnitTestCase
{
    use FilterTestTrait;

    protected function testFilterFailsOnAdminRoute()
    {
        $this->filtersConfig->globals['before'] = ['admin-only-filter'];

        $this->assertHasFilters('unfiltered/route', 'before');
    }

    // ...
}

ルートの確認

最初のヘルパーメソッドはgetFiltersForRoute()です。これは、指定されたルートをシミュレートし、コントローラーやルーティングコードを実行することなく、指定された位置(「before」または「after」)で実行されるすべてのフィルター(エイリアスによる)のリストを返します。これにより、コントローラーテストやHTTPテストと比較して、パフォーマンスが大幅に向上します。

getFiltersForRoute($route, $position)
パラメーター:
  • $route (string) – チェックするURI

  • $position (string) – チェックするフィルターメソッド、「before」または「after」

戻り値:

実行される各フィルターのエイリアス

戻り値の型:

string[]

使用例

<?php

$result = $this->getFiltersForRoute('/', 'after'); // ['toolbar']

フィルターメソッドの呼び出し

設定で説明されているプロパティはすべて、他のテストからの干渉や妨害なしに、最大限のパフォーマンスを確保するために設定されています。次のヘルパーメソッドは、これらのプロパティを使用してフィルターコードを安全にテストし、結果を確認するための呼び出し可能なメソッドを返します。

getFilterCaller($filter, $position)
パラメーター:
  • $filter (FilterInterface|string) – フィルターインスタンス、クラス、またはエイリアス

  • $position (string) – 実行するフィルターメソッド、「before」または「after」

戻り値:

シミュレートされたフィルターイベントを実行するための呼び出し可能なメソッド

戻り値の型:

Closure

使用例

<?php

namespace CodeIgniter;

use CodeIgniter\Test\CIUnitTestCase;
use CodeIgniter\Test\FilterTestTrait;

final class FilterTestCase extends CIUnitTestCase
{
    use FilterTestTrait;

    protected function testUnauthorizedAccessRedirects()
    {
        $caller = $this->getFilterCaller('permission', 'before');
        $result = $caller('MayEditWidgets');

        $this->assertInstanceOf('CodeIgniter\HTTP\RedirectResponse', $result);
    }
}

Closureは、フィルターメソッドに渡される入力パラメーターを取ることができることに注意してください。

アサーション

上記のヘルパーメソッドに加えて、FilterTestTraitには、テストメソッドを簡素化するいくつかのアサーションも含まれています。

assertFilter()

assertFilter()メソッドは、指定された位置にある指定されたルートが(エイリアスによる)フィルターを使用していることを確認します。

<?php

// Make sure users are logged in before checking their account
$this->assertFilter('users/account', 'before', 'login');

assertNotFilter()

assertNotFilter()メソッドは、指定された位置にある指定されたルートが(エイリアスによる)フィルターを使用していないことを確認します。

<?php

// Make sure API calls do not try to use the Debug Toolbar
$this->assertNotFilter('api/v1/widgets', 'after', 'toolbar');

assertHasFilters()

assertHasFilters()メソッドは、指定された位置にある指定されたルートに少なくとも1つのフィルターが設定されていることを確認します。

<?php

// Make sure that filters are enabled
$this->assertHasFilters('filtered/route', 'after');

assertNotHasFilters()

assertNotHasFilters()メソッドは、指定された位置にある指定されたルートにフィルターが設定されていないことを確認します。

<?php

// Make sure no filters run for our static pages
$this->assertNotHasFilters('about/contact', 'before');