2012-05-10 4 views
4

PHPUnit을 사용하여 테스트 용 mock 클래스를 만들고 있습니다.PHP 리플렉션을 사용하여 정적 속성을 설정하려면 어떻게해야합니까?

class Item extends Object { 
    protected static $_cache; 
} 

나는 (내가 틀렸다면 수정하시기 바랍니다) 꽤 특정 조롱이 같은 무언가를 생각 :

Item이의 캐시가 채워됩니다
class Mock_Item_randomstring extends Item { 

} 

, 객체 있는지 확인하는 것 전달되는 값은 Item입니다. 모의은 명시 적으로 $_cache을 정의하지 않으므로 인스턴스 유형에 대한 점검에 실패합니다.

PHP는 실제로 반사 기능을 전혀 문서화하지 않습니다. 클래스가

class Mock_Item_randomstring extends Item { 
    protected static $_cache; 
} 

편집

내가 반사 방법으로 주위를 연주하고 다양한 문제로 실행 될 것입니다 수 있도록 사후 정적 변수를 설정하는 방법이 있나요. 다음은 내가 혼란스러워하는 내용입니다 :

$mock = $this->getMock('Item', array('_func'), array(
    $argument1, $argument2 
)); 

$mock = new ReflectionClass($mock); 


$mock->staticExpects($this->exactly(2))->method('_func'); 

저는 전체의 반성을 복사했습니다.

물론
class A { 
    protected static $cache; 
    public static function getCache() { 
     return static::$cache; 
    } 
    public static function setCache($val) { 
     static::$cache = & $val; // note the '&' 
    } 
} 
class B extends A {} 

A::setCache('A'); 
B::setCache('B'); 
A::getCache(); // 'A' 
B::getCache(); // 'B' 

, 그것은 처음부터 정적 변수를 피하기 위해 최고 : 나는 서브 클래스에서, 클래스마다의 정적 변수에 다소 불쾌한 트릭을 사용하는 경향이 Call to undefined method ReflectionClass::staticExpects()

+1

에 대한 예제 코드를 참조하십시오. 그러나 종속성 삽입 기술을 사용하여 이러한 경우를 피할 필요가 있습니다. – zerkms

+0

static :: $ _ cache가 mock에 명시 적으로 정의되지 않았기 때문에 Item을 찾지 않으면이 문제를 완전히 피할 수 있습니다. PHP + 정적 물건의 지긋 지긋한 한계. 우리는 관리자 객체를 사용하지 않기 때문에 캐시와 정적 메소드를 사용한다. –

+0

정적 변수 *를 사용하면 문제가 생길 것입니다. (여기서하는 일은 기본적으로 싱글 톤이며 왜 악의적 인 이유인지 많이 읽을 수 있습니다.)하지만 왜 이것이 타입을 실패하게 만들지는 모르겠습니다. 검사. 코드를 게시 할 수 있습니까? (자식 클래스에서 같은 변수를 정의하여 달성하고자하는 것이 무엇인지 확실하지 않지만 여전히 부모와 값을 공유합니다.) – Tgr

답변

0

:이 오류 . 전용 캐시 오브젝트를 사용하고 클래스가 인스턴스화 될 때이를 주입하십시오.

+0

원래 질문에 답하기 위해 reflection은 클래스 정의를 허용하지 않습니다. PHPUnit (https : // github. 이미 정의 된 클래스를 변경하는 것보다 훨씬 적습니다 (runkit이 필요하고 상황이 중단 될 수 있습니다). 리플렉션을 사용하여 이미 존재하는 클래스의 비 public static 속성을 설정하는 것은 가능하지만 불쾌합니다. [setStaticPropertyValue에 대한 설명] (http://www.php.net/manual/en/reflectionclass.setstaticpropertyvalue.php)을 참조하십시오. – Tgr

+0

어떤 댓글이 있습니까? :) "이 페이지에 사용자가 제공 한 메모가 없습니다." 실제로 '모의 (mock)'안에있는 것처럼 사용하게 될까요? 아니면'Item' 안에있는 것처럼 설정하겠습니까? –

+0

내 잘못 - 나는 [getStaticPropertyValue] (http://www.php.net/manual/en/reflectionclass.getstaticpropertyvalue.php)에 대한 주석을 의미했지만, 그 동안 테스트 해봤지만 작동하지 않습니다. 'getProperty'를 사용하면/setAccessible/setValue는 5.3에서 작동하지만 미래에는 깨지지 않을 것입니다. (예를 들어 값을 읽는 데 같은 메소드가 작동하지 않습니다.) – Tgr

0

당신은 꼭 할 필요는 없습니다. \Closure::bind을 사용하면 개인 및 보호 된 정적 속성을 읽고 할당 할 수 있습니다. http://www.php.net/manual/en/closure.bind.php

+0

PHP 5.4 이상입니다. – Tgr

+0

나는 잠시 동안 5.4에 없을 것이다. 웃기는 점은 바인드 페이지의 5.4 페이지 만 언급하는 것이 아니라는 점입니다. http://www.php.net/manual/en/class.closure.php –

+0

5.4+가 문제를 해결하고 유일한 문제는 해결책은 수업을 재 설계하는 것입니다. 5.4에 빨리 착수하는 것이 어떻습니까? –

관련 문제