2012-08-09 4 views
2

세션 관리 클래스와 관련 단위 테스트를 구축 중입니다. 클래스를 $ _SESSION의 전역 상태와 분리하기 위해 클래스와 세션 데이터 간의 바인딩을 관리하기 위해 매우 간단한 클래스를 사용합니다. 나는 다음과 같은 한 소비 세션 클래스에서매번 동일한 배열을 반환하는 PHPUnit 모의

class Binding implements iface\Binding 
{ 
    public function &getNamespace ($namespace) 
    { 
     return $_SESSION [$namespace]; 
    } 
} 

: 다음과 같이

바인딩 클래스의 전체 소스는

protected function initStorage() 
{ 
    // Check that storage hasn't already been bound to the session 
    if ($this -> storage === NULL) 
    { 
     // Attempt to start the session if it hasn't already been started 
     if (($this -> sessionId() !== '') 
     || ((!$this -> headersSent()) 
     && ($this -> startSession()))) 
     { 
      // Bind the storage to the session 
      $this -> storage =& $this -> binding -> getNamespace ($this -> namespace); 
      // Make sure the session is in a usable state 
      if (!$this -> hasData()) 
      { 
       $this -> reset(); 
      } 
     } 
     else 
     { 
      // We couldn't start the session 
      throw new \RuntimeException (__METHOD__ . ': Unable to initiate session storage at this time'); 
     } 
    } 

    return $this; 
} 

sessionId가, headersSent 및 startSession 간단한 한 줄의 함수이다 PHPUnit에서 mocks로 쉽게 대체 할 수있는 "테스트 솔기"역할을합니다.

모의 바인딩 클래스로 세션을 분리하는 것보다 더 많은 작업을 할 수있는 테스트를 작성하면서 클래스의 비공개 속성을 관찰 할 필요없이 실제로 내부 상태를 노출시켜 클래스를 취약하게 만듭니다. 클래스가 배열에 직접 참조되기보다는 배열에 대한 참조로 작동하므로 참조되는 배열을 관찰 할 수 있습니다.

필자는 PHPUnit의 조롱 API를 사용하여이 작업을 수행하고 싶었지만 어떻게해야하는지 알 수 없습니다.

는 나는이 같은 배열을 반환하는 모의를 만들 수 있습니다 알고 : 그것은 다른 배열마다 시간을 반환로

$mock = $this -> getMock ('iface\Binding'); 

$mock -> expects ($this -> any()) 
     -> method ('getNamespace') 
     -> will ($this -> returnValue (array())); 

그것은, 비록 상태 변화를 관찰하는 데 유용하지 않습니다. 필요한 것은 매번 같은 배열에 대한 참조를 반환하는 모의 (mock)입니다.

class BindingMock implements iface\Binding 
{ 
    protected $storage = array(); 

    public function &getNamespace ($namespace) 
    { 
     return $this -> storage [$namespace]; 
    } 
} 

을이 클래스를 사용하여 날 이전과 뭔가를 호출 한 후 $ 저장의 내용을 검사 할 수 있습니다 : 결국

나는 진짜 Binding 클래스를 대신하고 그 대신에 사용하는 클래스를 썼다 세션 API에서 비공개 상태를 노출하지 않고도 스토리지 배열에있는 내용을 볼 수 있기 때문에 세션 API를 사용할 수 있습니다. 여기에 기술을 사용하는 예제 테스트는 다음과 같습니다

public function testCreateItem() 
{ 
    $storage =& $this -> binding -> getNamespace ('unittest'); 
    $this -> assertEmpty ($storage); 
    $this -> object -> createItem ('This is a test', 'test'); 
    $this -> assertNotEmpty ($storage); 
    $this -> assertEquals ('This is a test', $storage ['test']); 
} 
차라리 그냥 단위 테스트에 대한 추가 클래스를 가지고,하지만 phpunit을을 사용하여 대체 클래스를 생성 할 수있을 것

는하지 않는 한 그것을 할 수있는 잘못된 방법처럼 보인다 PHPUnit에서 같은 것을 달성 할 방법이 없습니다.

+0

Off topic ... 멋진 아바타! – Jrod

답변

0

내부 배열을 테스트에 노출하는 ArrayObject을 반환 할 수 있다고 생각하지만,이 경우 배열을 Binding에서 노출시키지 않는 것이 좋습니다. 대신, Binding 인터페이스는 다른 상위 레벨 조작과 함께 값을 가져오고 설정하고 지우는 메소드를 제공해야합니다. 그런 다음 원시 배열을 반환하는 호출이 아닌 해당 호출을 예상하는 mock 객체를 전달할 수 있습니다.

관련 문제