문제

저는 현재 제가 작성하고 있는 것과 함께 테스트를 개발하기 위해 PHPUnit을 사용하고 있습니다. 그러나 현재 Session Manager를 작성하는 중인데 문제가 있습니다...

세션 처리 클래스의 생성자는 다음과 같습니다.

private function __construct()
{
    if (!headers_sent())
    {
        session_start();
        self::$session_id = session_id();
    }
}

그러나 PHPUnit은 테스트를 시작하기 전에 텍스트를 전송하므로 이 객체에 대한 모든 테스트는 HTTP "헤더"가 전송되었기 때문에 실패한 테스트를 반환합니다.

도움이 되었습니까?

해결책

글쎄, 세션 관리자는 기본적으로 설계 상 손상되었습니다.무언가를 테스트하려면 부작용으로부터 격리할 수 있어야 합니다.불행하게도 PHP는 전역 상태(echo, header, exit, session_start 등.등.).

당신이 할 수 있는 가장 좋은 방법은 런타임에 교체될 수 있는 구성 요소의 부작용을 격리하는 것입니다.이렇게 하면 테스트에서는 모의 객체를 사용할 수 있고 라이브 코드에서는 실제 부작용이 있는 어댑터를 사용할 수 있습니다.당신은 이것이 당신이 사용하고 있다고 생각하는 싱글톤에서는 잘 작동하지 않는다는 것을 알게 될 것입니다.따라서 공유 객체를 코드에 배포하려면 다른 메커니즘을 사용해야 합니다.정적 레지스트리로 시작할 수 있지만 약간의 학습에 신경 쓰지 않는다면 더 나은 솔루션이 있습니다.

그렇게 할 수 없다면 항상 통합 테스트를 작성할 수 있는 옵션이 있습니다.예.PHPUnit과 동등한 것을 사용하십시오 WebTestCase.

다른 팁

PhPunit 용 부트 스트랩 파일을 작성하여 호출하십시오.

session_start();

그런 다음 다음과 같이 phpunit을 시작하십시오.

phpunit --bootstrap pathToBootstrap.php --anotherSwitch /your/test/path/

부트 스트랩 파일은 다른 모든 것보다 먼저 호출되므로 헤더가 전송되지 않고 모든 것이 잘 작동해야합니다.

PhPunit은 테스트가 실행될 때 출력을 인쇄하여 Headers_Sent ()가 첫 번째 테스트에서도 True를 반환합니다.

전체 테스트 스위트의 경우이 문제를 극복하려면 설정 스크립트에서 OB_START ()를 사용하면됩니다.

예를 들어, phpunit에서 가장 먼저로드 한 AllTests.php라는 파일이 있다고 가정 해 봅시다. 해당 스크립트는 다음과 같을 수 있습니다.

<?php

ob_start();

require_once 'YourFramework/AllTests.php';

class AllTests {
    public static function suite() {
        $suite = new PHPUnit_Framework_TestSuite('YourFramework');
        $suite->addTest(YourFramework_AllTests::suite());
        return $suite;
    }
}

나는 같은 문제를 겪었고 다음과 같이 -stderr 플래그로 phpunit을 호출하여 해결했습니다.

phpunit --stderr /path/to/your/test

누군가를 돕기를 바랍니다!

"올바른"솔루션은 PHP의 세션 관련 기능을위한 래퍼 인 매우 간단한 클래스 (테스트 할 필요가 없음)를 만드는 것입니다. session_start(), 직접.

테스트 패스 모의 객체에서 실제 상태가없는 테스트 할 수없는 세션 클래스 대신.

private function __construct(SessionWrapper $wrapper)
{
   if (!$wrapper->headers_sent())
   {
      $wrapper->session_start();
      $this->session_id = $wrapper->session_id();
   }
}

아무도 XDEBUG 옵션을 나열하지 않은 이유가 궁금합니다.

/**
 * @runInSeparateProcess
 * @requires extension xdebug
 */
public function testGivenHeaderIsIncludedIntoResponse()
{
    $customHeaderName = 'foo';
    $customHeaderValue = 'bar';

    // Here execute the code which is supposed to set headers
    // ...

    $expectedHeader = $customHeaderName . ': ' . $customHeaderValue;
    $headers = xdebug_get_headers();

    $this->assertContains($expectedHeader, $headers);
}

테스트를 시작하기 전에 출력 버퍼링을 사용할 수 없습니까? 출력되는 모든 것을 버퍼링하면 해당 시점에서 출력이 아직 클라이언트에 전송되지 않았기 때문에 헤더를 설정하는 데 문제가 없습니다.

OB가 클래스 내부의 어딘가에 사용 되더라도 쌓을 수 있으며 OB는 내부에서 일어나는 일에 영향을 미치지 않아야합니다.

내가 아는 한 Zend Framework는 Zend_session 패키지 테스트에 동일한 출력 버퍼링을 사용합니다. 테스트 사례를 살펴보고 시작할 수 있습니다.

4개의 게시물을 다시 지적한 부트스트랩 파일을 생성하는 것이 이 문제를 해결하는 가장 깔끔한 방법인 것 같습니다.

종종 우리는 PHP를 사용하여 엄청나게 결합된 레거시 프로젝트에 일종의 엔지니어링 원칙을 유지하고 추가하려고 노력해야 합니다.우리에게는 쓰레기 더미 전체를 버리고 다시 시작할 시간(또는 권한)이 없으므로 앞으로 나아갈 길로서 troelskn의 첫 번째 답변이 항상 가능한 것은 아닙니다.(초기 디자인으로 돌아갈 수 있다면 웹 개발 세계의 COBOL을 영속시키는 데 도움이 되기보다는 PHP를 완전히 버리고 Ruby나 Python과 같은 보다 현대적인 것을 사용할 수 있습니다.)

session_start 또는 setcookie를 사용하는 모듈에 대한 단위 테스트를 작성하려는 경우 부스트랩 파일에서 세션을 시작하면 이러한 문제가 발생합니다.

지금 내 부트 스트랩을 단위로 테스트하고 있기 때문에 (예, 대부분의 사람들이 그렇게하지 않는다는 것을 알고 있습니다), 나는 같은 문제 (Header () 및 session_start ())에 실행됩니다. 내가 찾은 솔루션은 다소 간단합니다. 단위 테스트 부트 스트랩에서 상수를 정의하고 헤더를 보내거나 세션을 시작하기 전에 간단히 확인합니다.

// phpunit_bootstrap.php
define('UNITTEST_RUNNING', true);

// bootstrap.php (application bootstrap)
defined('UNITTEST_RUNNING') || define('UNITTEST_RUNNING', false);
.....
if(UNITTEST_RUNNING===false){
    session_start();
}

나는 이것이 디자인에 의해 완벽하지 않다는 데 동의하지만, 기존 응용 프로그램을 단위로 테스트하고 있으며, 큰 부품을 다시 작성하는 것이 바람직하지 않습니다. 또한 동일한 논리를 사용하여 __call () 및 __set () 마법 메소드를 사용하여 개인 메소드를 테스트합니다.

public function __set($name, $value){
    if(UNITTEST_RUNNING===true){
       $name='_' . $name;
       $this->$name=$value;
    }
    throw new Exception('__set() can only be used when unittesting!');
 }

코드를 테스트 할 수 있도록 세션을 주입 해야하는 것 같습니다. 내가 사용한 가장 좋은 옵션은 AURA.AUTH 인증 프로세스를위한 AURA.AUTH입니다.

널 세션으로 Aura 테스트

Aura 프레임 워크는 아름답게 작성되었으며 다른 Aura 프레임 워크 종속성없이 자체적으로 Aura.auth를 사용할 수 있습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top