컨트롤러 테스트

몇 가지 새로운 헬퍼 클래스와 트레이트를 통해 컨트롤러 테스트가 편리해졌습니다. 컨트롤러를 테스트할 때, 전체 애플리케이션 부트스트랩 과정을 거치지 않고도 컨트롤러 내의 코드를 실행할 수 있습니다. 대부분의 경우 기능 테스트 도구를 사용하는 것이 더 간단하지만, 필요한 경우를 위해 이 기능도 제공됩니다.

참고

전체 프레임워크가 부트스트랩되지 않았기 때문에, 이 방법으로 컨트롤러를 테스트할 수 없는 경우가 있습니다.

헬퍼 트레이트

컨트롤러 테스트를 활성화하려면 테스트 내에서 ControllerTestTrait 트레이트를 사용해야 합니다:

<?php

namespace App\Controllers;

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

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

트레이트가 포함되면 요청 및 응답 클래스, 요청 본문, URI 등을 포함한 환경 설정을 시작할 수 있습니다. 컨트롤러의 완전한 정규화 클래스명을 controller() 메서드에 전달하여 사용할 컨트롤러를 지정합니다. 마지막으로 실행할 메서드 이름을 매개변수로 execute() 메서드를 호출합니다:

<?php

namespace App\Controllers;

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

class ForumControllerTest extends CIUnitTestCase
{
    use ControllerTestTrait;
    use DatabaseTestTrait;

    public function testShowCategories()
    {
        $result = $this->withUri('http://example.com/categories')
            ->controller(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');

두 번째 이후의 매개변수를 지정하여 컨트롤러 메서드에 전달할 수 있습니다.

이 메서드는 응답 자체를 확인하기 위한 여러 루틴을 제공하는 새로운 헬퍼 클래스를 반환합니다. 자세한 내용은 아래를 참조하십시오.

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 인스턴스를 가져야 하기 때문입니다. 또한 URI 문자열의 호스트명이 Config\App에서 유효하지 않은 경우, 유효한 호스트명이 설정됩니다.

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 App\Filters;

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

class FooFilterTest extends CIUnitTestCase
{
    use FilterTestTrait;
}

설정

컨트롤러 테스트와의 논리적 중복으로 인해, FilterTestTrait은 동일한 클래스에서 둘 다 필요한 경우 ControllerTestTrait과 함께 동작하도록 설계되었습니다. 트레이트가 포함되면 CIUnitTestCasesetUp 메서드를 감지하고 테스트에 필요한 모든 컴포넌트를 준비합니다. 특수한 설정이 필요한 경우, 지원 메서드를 호출하기 전에 속성을 변경할 수 있습니다:

  • $request 기본 IncomingRequest 서비스의 준비된 버전

  • $response 기본 ResponseInterface 서비스의 준비된 버전

  • $filtersConfig 기본 Config\Filters 설정 (참고: 검색은 Filters에 의해 처리되므로 모듈 별칭은 포함되지 않습니다)

  • $filters 위의 세 컴포넌트를 사용하는 CodeIgniter\Filters\Filters 인스턴스

  • $collection Config\Routes 검색을 포함하는 RouteCollection의 준비된 버전

기본 설정은 “라이브” 프로젝트를 가장 가깝게 에뮬레이션하므로 일반적으로 테스트에 가장 적합합니다. 하지만 예를 들어 필터가 걸려있지 않은 라우트에서 실수로 필터가 트리거되는 것을 시뮬레이션하려면 Config에 추가할 수 있습니다:

<?php

namespace App\Filters;

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

final class FooFilterTest 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']

필터 메서드 호출

설정 섹션에서 설명한 속성들은 다른 테스트의 간섭이나 영향 없이 최대 성능을 보장하도록 모두 설정됩니다. 다음 헬퍼 메서드는 이러한 속성들을 사용하여 필터 코드를 안전하게 테스트하고 결과를 확인하는 callable 메서드를 반환합니다.

getFilterCaller($filter, $position)
매개변수:
  • $filter (FilterInterface|string) – 필터 인스턴스, 클래스 또는 별칭

  • $position (string) – 실행할 필터 메서드, “before” 또는 “after”

반환:

시뮬레이션된 필터 이벤트를 실행하는 callable 메서드

반환 형식:

Closure

사용 예시:

<?php

namespace App\Filters;

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

final class FooFilterTest 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() 메서드는 특정 위치의 주어진 라우트에 최소 하나 이상의 필터가 설정되어 있는지 확인합니다:

<?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');