2009-07-22 4 views
20

SimpleTest에서 PHPUnit으로 많은 테스트를 마이그레이션하려고합니다. SimpleTest의 partial mocks에 해당하는 것이 있는지 궁금합니다.PHPUnit의 SimpleTest "partial mocks"와 동일합니까?

업데이트 :이 기능을 사용할 수 있다고 제안하는 문서에서는 아무 것도 찾을 수 없지만 하위 클래스 만 사용할 수 있습니다. 이것은 좋은 생각입니까 아니면 나쁜 생각입니까? 링크 된 페이지를 읽고에서

class StuffDoer { 
    protected function doesLongRunningThing() { 
     sleep(10); 
     return "stuff"; 
    } 
    public function doStuff() { 
     return $this->doesLongRunningThing(); 
    } 
} 
class StuffDoerTest { 
    protected function doesLongRunningThing() { 
     return "test stuff"; 
    } 
} 
class StuffDoerTestCase extends PHPUnit_Framework_TestCase { 
    public function testStuffDoer() { 
     $sd = new StuffDoerTest(); 
     $result = $sd->doStuff(); 
     $this->assertEquals($result, "test stuff"); 
    } 
} 
+0

하위 클래스 아이디어에 감사드립니다! – Kyslik

답변

40

는 SimpleTest 부분 모의는 방법 중 일부는 오버라이드 (override)하는 경우에만 모의 것 같다. 이것이 맞다면, 그 기능은 일반적인 PHPUnit 모의에 의해 처리됩니다.

PHPUnit_Framework_TestCase 내부, 모든 방법이 아무것도하지 않고 null을 돌려 주어 모의 인스턴스를 생성

$mock = $this->getMock('Class_To_Mock'); 

와 가짜를 만들 수 있습니다. 일부 메서드 만 재정의하려는 경우 getMock의 두 번째 매개 변수는 재정의 할 메서드의 배열입니다.

$mock = $this->getMock('Class_To_Mock', array('insert', 'update')); 

는 반환 값이 지정 될 준비가 제거 insertupdate 기능과 Class_To_Mock의 모의 인스턴스를 생성합니다.

이 정보는 phpunit docs에 있습니다.

, this answer 5.4

1

내가 phpunit을 테스트중인 시스템에 대한 부분적인 망신 시켰를 지원합니다 생각하지 않습니다 시작 phpunit을 버전의 날짜 코드 예제까지 더 보여줍니다. 메서드를 분리하려고한다면 구현이 제대로 작동하는지 확신합니다.

그러나 저는 이것을 피하려고합니다. 몇 가지 이유가 있습니다.

먼저 테스트를 클래스의 내부 구현과 매우 긴밀하게 연결합니다. doesLongRunningThing이라는 메서드가 호출되었는지 정말로 신경 씁니까, 아니면 "LongRunningThing"이 완료된 것이 더 중요합니까?

둘째로, 내가이 문제에 부딪치게되면 항상 두 가지 일을하는 한 반을 가지고 있는지 궁금하게됩니다. 추출 클래스 리팩토링이 필요할 수 있습니다. doesLongRunningThing()이 단일 메소드로도 자체 클래스가되면 테스트가 훨씬 쉬워집니다.

SUT가 의존하는 서비스를 삽입하는 것이 해결책이라고 생각합니다 (http://en.wikipedia.org/wiki/Dependency_injection). 이것은 또한 DoesLongRunningThing 구현을 더 테스트 가능하게 만듭니다. 인터페이스에 뛰어없이

, 여기에 내가 할 것이 무엇 :

class DoesLongRunningThing { 
    public function execute() { 
     sleep(10); 
     return "stuff"; 
    } 
} 

class StuffDoer { 
    protected $doesLongRunningThing; 

    public function setLongRunningThinger(DoesLongRunningThing $obj) { 
     $this->doesLongRunningThing = $obj; 
    } 

    public function doStuff() { 
     return $this->doesLongRunningThing->execute(); 
    } 
} 

지금은 모의에 쉽게 :

class StuffDoerTestCase extends PHPUnit_Framework_TestCase { 
    public function testStuffDoer() { 
     $dlrtMock = $this->getMock('DoesLongRunningThing'); 
     $dlrtMock->expects($this->any())->will($this->returnValue("test stuff")); 

     $sd = new StuffDoer(); 
     $sd->setLongRunningThinger($dlrtMock); 
     $result = $sd->doStuff(); 
     $this->assertEquals($result, "test stuff"); 
    } 
} 
+0

필자는 PHPUnit이 도구 일 뿐이며 테스트중인 시스템은 신경 쓰지 않는다 (도구 사용자의 거래). Brenton의 대답에 따르면, PHPUnit은 "부분적인 조롱"을 지원합니다. 첫 번째 문장 다음에 시작하면 답이 완벽합니다 (+1). –

8

PHPUnit_Framework_TestCase::getMock is deprecated since phpunit 5.4. 대신 setMethods을 사용할 수 있습니다.

모의 작성기 개체에서 setMethods (array $ methods)를 호출하여 구성 가능한 테스트 이중으로 대체 할 메서드를 지정할 수 있습니다. 다른 메소드의 동작은 변경되지 않습니다. setMethods (null)를 호출하면 (자), 메소드는 치환되지 않습니다.

상기 getMockPHPUnit_Framework_MockObject_MockBuilder::getMock는 것을 https://phpunit.de/manual/current/en/test-doubles.html

$observer = $this->getMockBuilder(Observer::class) 
       ->setMethods(['update']) 
       ->getMock(); 

참고. (phpunit5.6)