2009-05-24 5 views
1

몇 가지 테스트 케이스를 작성 중이며 Mock 객체를 사용하는 테스트 케이스가 있습니다. 두 클래스 메서드가 다른 클래스 메서드에서 호출되는지 확인해야합니다. 여기에 내가 무슨 짓을했는지의 :SimpleTest Mocking Problem

먼저 내가 모의 생성 :

Mock::generate('Parser'); 

그런 다음 내 테스트 안에 내가 전화 :

public function fetchAndParse($url) { 
    $this->loadUrl($url); 
    $this->parse(); 
} 
:

$P = new MockParser(); 

$P->expectOnce('loadUrl', array('http://url')); 
$P->expectOnce('parse'); 

$P->fetchAndParse('http://url'); 

내 구현 코드는 같다

그리고 loadUrl과 parse() 메소드가 존재합니다. 내 테스트에서 두 가지 실패가 나타납니다. 둘 다 "[loadUrl]의 예상 호출 횟수는 [1] [0]입니다. 무슨 일이 벌어지고 있는지 전혀 모르겠다 - 그 함수에서 메서드가 호출되고있다!

감사합니다,

제이미 내 경험이 .NET 세계에서 프레임 워크를 조롱와 함께왔다 동안

답변

4

, 난 당신이 뭘 하려는지 것은 잘못이라고 생각합니다.

클래스 용 모의 객체를 생성하라는 메시지가 표시되면 임의의 조롱 프레임 워크가 해당 클래스의 모든 메소드에 대해 "스텁"을 생성합니다. 여기에는 fetchAndParse 메소드가 포함됩니다. 따라서 모의 객체 $ P에서 fetchAndParse를 호출하면 loadUrl 및 parse 메소드가 호출되지 않습니다. 당신이 실제로하고있는 일은 "stubbed"fetchAndParse 메서드를 호출하는 것입니다.

저는 PHP에 익숙하지 않아 테스트를 시도하고 싶지 않습니다. 바라건대 다른 누군가가 그렇게 할 수 있기를 바랍니다.

+0

정말 도움이 되네요. 코드를 꽤 많이 바꿔야한다는 것을 의미합니다.하지만 적어도 지금 무슨 일이 일어나고 있는지 알고 있습니다! 감사! –

1

당신은 조롱이 어떻게 작동하는지 오해했습니다. 의존성 삽입을 사용하여 클래스에서 도우미 객체를 설정하면 삽입 된 객체를 조롱 할 수 있습니다. 그런 다음 원본 개체의 동작 (인터페이스)을 시뮬레이션 할 수 있습니다. 더 좋은 방법은 현재 인터페이스를 구현하는 클래스를 만들지 않고 개발할 수 있기 때문에 인터페이스를 모방하는 것입니다. 귀하의 예에 의하여

:

Btw는
interface UrlLoaderInterface { 

    public function load($url); 
} 

class YourParser { 

    protected $urlLoader; 
    protected $source; 

    public function setUrlLoader(UrlLoaderInterface $urlLoader) { 
     $this->urlLoader = $urlLoader; 
    } 

    public function fetchAndParse($url) { 
     $this->loadUrl($url); 
     $this->parse(); 
    } 

    public function loadUrl($url) { 
     $this->source = $this->urlLoader->load($url); 
    } 

    public function parse() { 

    } 

} 

Mock::generate('UrlLoaderInterface', 'MockUrlLoader'); 

class TestYourParser extends UnitTestCase { 

    public function testShouldCallUrlLoaderByFetchAndParse() { 
     $testUrl = 'http://url'; 

     $urlLoader = new MockUrlLoader(); 
     $urlLoader->expectOnce('load', array($testUrl)); 
     $urlLoader->returns('load', 'source', array($testUrl)); 

     $parser = new YourParser(); 
     $parser->setUrlLoader($urlLoader); 
     $parser->fetchAndParse($testUrl); 
    } 

} 

. 메서드 이름에 'and', ',', 'if'등의 단어가 포함될 수 없기 때문에 예제는 실패한 것입니다. 메서드는 한 가지만 수행 할 수 있습니다. 이 단어들을 사용하면 잘못된 설계 코드가 있음을 확신 할 수 있습니다.